Merge miscellaneous omapdss changes
Most important changes: * Remove OMAP4 HDMI gpio handling from board files * Add vdda_hdmi_dac supply for HDMI to twl-common.c * Calculate DSI clocks dynamically * Remove DSS clock dividers from 4430sdp board file * vram.c no longer uses OMAP's sDMA to clear the memory * Fifomerge has been reverted * Swap GFX and WB fifos to avoid underflows
This commit is contained in:
commit
6cd05430ee
32 changed files with 1424 additions and 1467 deletions
|
|
@ -601,29 +601,6 @@ static void __init omap_sfh7741prox_init(void)
|
|||
__func__, OMAP4_SFH7741_ENABLE_GPIO, error);
|
||||
}
|
||||
|
||||
static struct gpio sdp4430_hdmi_gpios[] = {
|
||||
{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
|
||||
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
|
||||
{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
|
||||
};
|
||||
|
||||
static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = gpio_request_array(sdp4430_hdmi_gpios,
|
||||
ARRAY_SIZE(sdp4430_hdmi_gpios));
|
||||
if (status)
|
||||
pr_err("%s: Cannot request HDMI GPIOs\n", __func__);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
|
||||
{
|
||||
gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
|
||||
}
|
||||
|
||||
static struct nokia_dsi_panel_data dsi1_panel = {
|
||||
.name = "taal",
|
||||
.reset_gpio = 102,
|
||||
|
|
@ -644,29 +621,6 @@ static struct omap_dss_device sdp4430_lcd_device = {
|
|||
.phy.dsi = {
|
||||
.module = 0,
|
||||
},
|
||||
|
||||
.clocks = {
|
||||
.dispc = {
|
||||
.channel = {
|
||||
/* Logic Clock = 172.8 MHz */
|
||||
.lck_div = 1,
|
||||
/* Pixel Clock = 34.56 MHz */
|
||||
.pck_div = 5,
|
||||
.lcd_clk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
|
||||
},
|
||||
.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
|
||||
},
|
||||
|
||||
.dsi = {
|
||||
.regn = 16, /* Fint = 2.4 MHz */
|
||||
.regm = 180, /* DDR Clock = 216 MHz */
|
||||
.regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */
|
||||
.regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */
|
||||
|
||||
.lp_clk_div = 10, /* LP Clock = 8.64 MHz */
|
||||
.dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
|
||||
},
|
||||
},
|
||||
.channel = OMAP_DSS_CHANNEL_LCD,
|
||||
};
|
||||
|
||||
|
|
@ -691,33 +645,12 @@ static struct omap_dss_device sdp4430_lcd2_device = {
|
|||
|
||||
.module = 1,
|
||||
},
|
||||
|
||||
.clocks = {
|
||||
.dispc = {
|
||||
.channel = {
|
||||
/* Logic Clock = 172.8 MHz */
|
||||
.lck_div = 1,
|
||||
/* Pixel Clock = 34.56 MHz */
|
||||
.pck_div = 5,
|
||||
.lcd_clk_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
|
||||
},
|
||||
.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
|
||||
},
|
||||
|
||||
.dsi = {
|
||||
.regn = 16, /* Fint = 2.4 MHz */
|
||||
.regm = 180, /* DDR Clock = 216 MHz */
|
||||
.regm_dispc = 5, /* PLL1_CLK1 = 172.8 MHz */
|
||||
.regm_dsi = 5, /* PLL1_CLK2 = 172.8 MHz */
|
||||
|
||||
.lp_clk_div = 10, /* LP Clock = 8.64 MHz */
|
||||
.dsi_fclk_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
|
||||
},
|
||||
},
|
||||
.channel = OMAP_DSS_CHANNEL_LCD2,
|
||||
};
|
||||
|
||||
static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
|
||||
.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
|
||||
.ls_oe_gpio = HDMI_GPIO_LS_OE,
|
||||
.hpd_gpio = HDMI_GPIO_HPD,
|
||||
};
|
||||
|
||||
|
|
@ -725,8 +658,6 @@ static struct omap_dss_device sdp4430_hdmi_device = {
|
|||
.name = "hdmi",
|
||||
.driver_name = "hdmi_panel",
|
||||
.type = OMAP_DISPLAY_TYPE_HDMI,
|
||||
.platform_enable = sdp4430_panel_enable_hdmi,
|
||||
.platform_disable = sdp4430_panel_disable_hdmi,
|
||||
.channel = OMAP_DSS_CHANNEL_DIGIT,
|
||||
.data = &sdp4430_hdmi_data,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -408,30 +408,9 @@ static struct omap_dss_device omap4_panda_dvi_device = {
|
|||
.channel = OMAP_DSS_CHANNEL_LCD2,
|
||||
};
|
||||
|
||||
static struct gpio panda_hdmi_gpios[] = {
|
||||
{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
|
||||
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
|
||||
{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
|
||||
};
|
||||
|
||||
static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = gpio_request_array(panda_hdmi_gpios,
|
||||
ARRAY_SIZE(panda_hdmi_gpios));
|
||||
if (status)
|
||||
pr_err("Cannot request HDMI GPIOs\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
|
||||
{
|
||||
gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
|
||||
}
|
||||
|
||||
static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
|
||||
.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
|
||||
.ls_oe_gpio = HDMI_GPIO_LS_OE,
|
||||
.hpd_gpio = HDMI_GPIO_HPD,
|
||||
};
|
||||
|
||||
|
|
@ -439,8 +418,6 @@ static struct omap_dss_device omap4_panda_hdmi_device = {
|
|||
.name = "hdmi",
|
||||
.driver_name = "hdmi_panel",
|
||||
.type = OMAP_DISPLAY_TYPE_HDMI,
|
||||
.platform_enable = omap4_panda_panel_enable_hdmi,
|
||||
.platform_disable = omap4_panda_panel_disable_hdmi,
|
||||
.channel = OMAP_DSS_CHANNEL_DIGIT,
|
||||
.data = &omap4_panda_hdmi_data,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -258,6 +258,10 @@ static struct twl4030_usb_data omap4_usb_pdata = {
|
|||
.phy_suspend = omap4430_phy_suspend,
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply omap4_vdda_hdmi_dac_supplies[] = {
|
||||
REGULATOR_SUPPLY("vdda_hdmi_dac", "omapdss_hdmi"),
|
||||
};
|
||||
|
||||
static struct regulator_init_data omap4_vdac_idata = {
|
||||
.constraints = {
|
||||
.min_uV = 1800000,
|
||||
|
|
@ -267,6 +271,8 @@ static struct regulator_init_data omap4_vdac_idata = {
|
|||
.valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
| REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(omap4_vdda_hdmi_dac_supplies),
|
||||
.consumer_supplies = omap4_vdda_hdmi_dac_supplies,
|
||||
.supply_regulator = "V2V1",
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <plat/dma.h>
|
||||
#include "omapfb.h"
|
||||
|
||||
#define HWA742_REV_CODE_REG 0x0
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <linux/gpio.h>
|
||||
|
||||
#include <plat/board-ams-delta.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "omapfb.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <plat/fpga.h>
|
||||
#include "omapfb.h"
|
||||
|
||||
static int palmte_panel_init(struct lcd_panel *panel,
|
||||
|
|
|
|||
|
|
@ -131,15 +131,6 @@ static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
|
|||
* LCD controller and LCD DMA
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
/* Lookup table to map elem size to elem type. */
|
||||
static const int dma_elem_type[] = {
|
||||
0,
|
||||
OMAP_DMA_DATA_TYPE_S8,
|
||||
OMAP_DMA_DATA_TYPE_S16,
|
||||
0,
|
||||
OMAP_DMA_DATA_TYPE_S32,
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocate resources needed for LCD controller and LCD DMA operations. Video
|
||||
* memory is allocated from system memory according to the virtual display
|
||||
|
|
|
|||
|
|
@ -489,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
|
|||
dssdev->panel.timings.y_res = 480;
|
||||
dssdev->ctrl.pixel_size = 16;
|
||||
dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.max_brightness = 127;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,18 @@ struct taal_data {
|
|||
|
||||
struct omap_dss_device *dssdev;
|
||||
|
||||
/* panel specific HW info */
|
||||
struct panel_config *panel_config;
|
||||
|
||||
/* panel HW configuration from DT or platform data */
|
||||
int reset_gpio;
|
||||
int ext_te_gpio;
|
||||
|
||||
bool use_dsi_backlight;
|
||||
|
||||
struct omap_dsi_pin_config pin_config;
|
||||
|
||||
/* runtime variables */
|
||||
bool enabled;
|
||||
u8 rotate;
|
||||
bool mirror;
|
||||
|
|
@ -145,16 +157,8 @@ struct taal_data {
|
|||
bool ulps_enabled;
|
||||
unsigned ulps_timeout;
|
||||
struct delayed_work ulps_work;
|
||||
|
||||
struct panel_config *panel_config;
|
||||
};
|
||||
|
||||
static inline struct nokia_dsi_panel_data
|
||||
*get_panel_data(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
return (struct nokia_dsi_panel_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static void taal_esd_work(struct work_struct *work);
|
||||
static void taal_ulps_work(struct work_struct *work);
|
||||
|
||||
|
|
@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
|
|||
static int taal_enter_ulps(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
if (td->ulps_enabled)
|
||||
|
|
@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
|
||||
if (gpio_is_valid(td->ext_te_gpio))
|
||||
disable_irq(gpio_to_irq(td->ext_te_gpio));
|
||||
|
||||
omapdss_dsi_display_disable(dssdev, false, true);
|
||||
|
||||
|
|
@ -405,7 +409,6 @@ err:
|
|||
static int taal_exit_ulps(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
if (!td->ulps_enabled)
|
||||
|
|
@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
|
|||
goto err2;
|
||||
}
|
||||
|
||||
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
|
||||
if (gpio_is_valid(td->ext_te_gpio))
|
||||
enable_irq(gpio_to_irq(td->ext_te_gpio));
|
||||
|
||||
taal_queue_ulps_work(dssdev);
|
||||
|
||||
|
|
@ -438,7 +442,8 @@ err2:
|
|||
|
||||
r = taal_panel_reset(dssdev);
|
||||
if (!r) {
|
||||
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
|
||||
if (gpio_is_valid(td->ext_te_gpio))
|
||||
enable_irq(gpio_to_irq(td->ext_te_gpio));
|
||||
td->ulps_enabled = false;
|
||||
}
|
||||
err1:
|
||||
|
|
@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = {
|
|||
static void taal_hw_reset(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
|
||||
if (panel_data->reset_gpio == -1)
|
||||
if (!gpio_is_valid(td->reset_gpio))
|
||||
return;
|
||||
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
gpio_set_value(td->reset_gpio, 1);
|
||||
if (td->panel_config->reset_sequence.high)
|
||||
udelay(td->panel_config->reset_sequence.high);
|
||||
/* reset the panel */
|
||||
gpio_set_value(panel_data->reset_gpio, 0);
|
||||
gpio_set_value(td->reset_gpio, 0);
|
||||
/* assert reset */
|
||||
if (td->panel_config->reset_sequence.low)
|
||||
udelay(td->panel_config->reset_sequence.low);
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
gpio_set_value(td->reset_gpio, 1);
|
||||
/* wait after releasing reset */
|
||||
if (td->panel_config->sleep.hw_reset)
|
||||
msleep(td->panel_config->sleep.hw_reset);
|
||||
}
|
||||
|
||||
static void taal_probe_pdata(struct taal_data *td,
|
||||
const struct nokia_dsi_panel_data *pdata)
|
||||
{
|
||||
td->reset_gpio = pdata->reset_gpio;
|
||||
|
||||
if (pdata->use_ext_te)
|
||||
td->ext_te_gpio = pdata->ext_te_gpio;
|
||||
else
|
||||
td->ext_te_gpio = -1;
|
||||
|
||||
td->esd_interval = pdata->esd_interval;
|
||||
td->ulps_timeout = pdata->ulps_timeout;
|
||||
|
||||
td->use_dsi_backlight = pdata->use_dsi_backlight;
|
||||
|
||||
td->pin_config = pdata->pin_config;
|
||||
}
|
||||
|
||||
static int taal_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct taal_data *td;
|
||||
struct backlight_device *bldev = NULL;
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
struct panel_config *panel_config = NULL;
|
||||
int r, i;
|
||||
const char *panel_name;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
||||
if (!panel_data || !panel_data->name) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL);
|
||||
if (!td)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, td);
|
||||
td->dssdev = dssdev;
|
||||
|
||||
if (dssdev->data) {
|
||||
const struct nokia_dsi_panel_data *pdata = dssdev->data;
|
||||
|
||||
taal_probe_pdata(td, pdata);
|
||||
|
||||
panel_name = pdata->name;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (panel_name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
|
||||
if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
|
||||
panel_config = &panel_configs[i];
|
||||
if (strcmp(panel_name, panel_configs[i].name) == 0) {
|
||||
td->panel_config = &panel_configs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!panel_config) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (!td->panel_config)
|
||||
return -EINVAL;
|
||||
|
||||
dssdev->panel.timings = panel_config->timings;
|
||||
dssdev->panel.timings = td->panel_config->timings;
|
||||
dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
|
||||
|
||||
td = kzalloc(sizeof(*td), GFP_KERNEL);
|
||||
if (!td) {
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
td->dssdev = dssdev;
|
||||
td->panel_config = panel_config;
|
||||
td->esd_interval = panel_data->esd_interval;
|
||||
td->ulps_enabled = false;
|
||||
td->ulps_timeout = panel_data->ulps_timeout;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
|
||||
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
|
||||
|
||||
mutex_init(&td->lock);
|
||||
|
||||
atomic_set(&td->do_update, 0);
|
||||
|
||||
if (gpio_is_valid(td->reset_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "taal rst");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to request reset gpio\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_is_valid(td->ext_te_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio,
|
||||
GPIOF_IN, "taal irq");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "GPIO request failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio),
|
||||
taal_te_isr,
|
||||
IRQF_TRIGGER_RISING,
|
||||
"taal vsync", dssdev);
|
||||
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "IRQ request failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
|
||||
taal_te_timeout_work_callback);
|
||||
|
||||
dev_dbg(&dssdev->dev, "Using GPIO TE\n");
|
||||
}
|
||||
|
||||
td->workqueue = create_singlethread_workqueue("taal_esd");
|
||||
if (td->workqueue == NULL) {
|
||||
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
|
||||
r = -ENOMEM;
|
||||
goto err_wq;
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
|
||||
INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, td);
|
||||
|
||||
if (gpio_is_valid(panel_data->reset_gpio)) {
|
||||
r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
|
||||
"taal rst");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to request reset gpio\n");
|
||||
goto err_rst_gpio;
|
||||
}
|
||||
}
|
||||
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
if (panel_data->use_dsi_backlight) {
|
||||
if (td->use_dsi_backlight) {
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 255;
|
||||
|
||||
|
|
@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
taal_bl_update_status(bldev);
|
||||
}
|
||||
|
||||
if (panel_data->use_ext_te) {
|
||||
int gpio = panel_data->ext_te_gpio;
|
||||
|
||||
r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "GPIO request failed\n");
|
||||
goto err_gpio;
|
||||
}
|
||||
|
||||
r = request_irq(gpio_to_irq(gpio), taal_te_isr,
|
||||
IRQF_TRIGGER_RISING,
|
||||
"taal vsync", dssdev);
|
||||
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "IRQ request failed\n");
|
||||
gpio_free(gpio);
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
|
||||
taal_te_timeout_work_callback);
|
||||
|
||||
dev_dbg(&dssdev->dev, "Using GPIO TE\n");
|
||||
}
|
||||
|
||||
r = omap_dsi_request_vc(dssdev, &td->channel);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to get virtual channel\n");
|
||||
|
|
@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
err_vc_id:
|
||||
omap_dsi_release_vc(dssdev, td->channel);
|
||||
err_req_vc:
|
||||
if (panel_data->use_ext_te)
|
||||
free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
|
||||
err_irq:
|
||||
if (panel_data->use_ext_te)
|
||||
gpio_free(panel_data->ext_te_gpio);
|
||||
err_gpio:
|
||||
if (bldev != NULL)
|
||||
backlight_device_unregister(bldev);
|
||||
err_bl:
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_free(panel_data->reset_gpio);
|
||||
err_rst_gpio:
|
||||
destroy_workqueue(td->workqueue);
|
||||
err_wq:
|
||||
kfree(td);
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit taal_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
struct backlight_device *bldev;
|
||||
|
||||
dev_dbg(&dssdev->dev, "remove\n");
|
||||
|
|
@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
|
|||
sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
|
||||
omap_dsi_release_vc(dssdev, td->channel);
|
||||
|
||||
if (panel_data->use_ext_te) {
|
||||
int gpio = panel_data->ext_te_gpio;
|
||||
free_irq(gpio_to_irq(gpio), dssdev);
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
||||
bldev = td->bldev;
|
||||
if (bldev != NULL) {
|
||||
bldev->props.power = FB_BLANK_POWERDOWN;
|
||||
|
|
@ -1040,21 +1042,15 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
|
|||
|
||||
/* reset, to be sure that the panel is in a valid state */
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_free(panel_data->reset_gpio);
|
||||
|
||||
kfree(td);
|
||||
}
|
||||
|
||||
static int taal_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
||||
r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config);
|
||||
r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to configure DSI pins\n");
|
||||
goto err0;
|
||||
|
|
@ -1065,6 +1061,12 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
|
||||
omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
|
||||
|
||||
r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
r = omapdss_dsi_display_enable(dssdev);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable DSI\n");
|
||||
|
|
@ -1361,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
|
||||
|
|
@ -1385,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
|
||||
schedule_delayed_work(&td->te_timeout_work,
|
||||
msecs_to_jiffies(250));
|
||||
atomic_set(&td->do_update, 1);
|
||||
|
|
@ -1424,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev)
|
|||
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
if (enable)
|
||||
|
|
@ -1432,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
|||
else
|
||||
r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
|
||||
|
||||
if (!panel_data->use_ext_te)
|
||||
if (!gpio_is_valid(td->ext_te_gpio))
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
|
||||
if (td->panel_config->sleep.enable_te)
|
||||
|
|
@ -1742,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work)
|
|||
struct taal_data *td = container_of(work, struct taal_data,
|
||||
esd_work.work);
|
||||
struct omap_dss_device *dssdev = td->dssdev;
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
u8 state1, state2;
|
||||
int r;
|
||||
|
||||
|
|
@ -1789,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work)
|
|||
}
|
||||
/* Self-diagnostics result is also shown on TE GPIO line. We need
|
||||
* to re-enable TE after self diagnostics */
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
|
||||
r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
|
||||
if (r)
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -119,8 +119,8 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
|||
}
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio)) {
|
||||
r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
|
||||
"tfp410 pd");
|
||||
r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "tfp410 pd");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
|
||||
ddata->pd_gpio);
|
||||
|
|
@ -135,8 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
|||
if (!adapter) {
|
||||
dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
|
||||
i2c_bus_num);
|
||||
r = -EINVAL;
|
||||
goto err_i2c;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ddata->i2c_adapter = adapter;
|
||||
|
|
@ -145,10 +144,6 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
|||
dev_set_drvdata(&dssdev->dev, ddata);
|
||||
|
||||
return 0;
|
||||
err_i2c:
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_free(ddata->pd_gpio);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit tfp410_remove(struct omap_dss_device *dssdev)
|
||||
|
|
@ -160,9 +155,6 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)
|
|||
if (ddata->i2c_adapter)
|
||||
i2c_put_adapter(ddata->i2c_adapter);
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_free(ddata->pd_gpio);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, NULL);
|
||||
|
||||
mutex_unlock(&ddata->lock);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
|
||||
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
|
||||
manager.o overlay.o apply.o
|
||||
manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
|
||||
|
|
|
|||
|
|
@ -111,9 +111,6 @@ static struct {
|
|||
struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
|
||||
struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
|
||||
|
||||
bool fifo_merge_dirty;
|
||||
bool fifo_merge;
|
||||
|
||||
bool irq_enabled;
|
||||
} dss_data;
|
||||
|
||||
|
|
@ -677,40 +674,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
|
|||
mp->shadow_extra_info_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_write_regs_common(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
int i;
|
||||
|
||||
if (!dss_data.fifo_merge_dirty)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct mgr_priv_data *mp;
|
||||
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (mp->enabled) {
|
||||
if (dss_data.fifo_merge_dirty) {
|
||||
dispc_enable_fifomerge(dss_data.fifo_merge);
|
||||
dss_data.fifo_merge_dirty = false;
|
||||
}
|
||||
|
||||
if (mp->updating)
|
||||
mp->shadow_info_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dss_write_regs(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
int i;
|
||||
|
||||
dss_write_regs_common();
|
||||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct mgr_priv_data *mp;
|
||||
|
|
@ -799,8 +767,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
|||
dss_mgr_write_regs(mgr);
|
||||
dss_mgr_write_regs_extra(mgr);
|
||||
|
||||
dss_write_regs_common();
|
||||
|
||||
mp->updating = true;
|
||||
|
||||
if (!dss_data.irq_enabled && need_isr())
|
||||
|
|
@ -984,20 +950,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
|
|||
op->extra_info_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_apply_fifo_merge(bool use_fifo_merge)
|
||||
{
|
||||
if (dss_data.fifo_merge == use_fifo_merge)
|
||||
return;
|
||||
|
||||
dss_data.fifo_merge = use_fifo_merge;
|
||||
dss_data.fifo_merge_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
|
||||
bool use_fifo_merge)
|
||||
static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
|
||||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
u32 fifo_low, fifo_high;
|
||||
bool use_fifo_merge = false;
|
||||
|
||||
if (!op->enabled && !op->enabling)
|
||||
return;
|
||||
|
|
@ -1008,8 +965,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
|
|||
dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
|
||||
}
|
||||
|
||||
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
|
||||
bool use_fifo_merge)
|
||||
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct omap_overlay *ovl;
|
||||
struct mgr_priv_data *mp;
|
||||
|
|
@ -1020,10 +976,10 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
|
|||
return;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list)
|
||||
dss_ovl_setup_fifo(ovl, use_fifo_merge);
|
||||
dss_ovl_setup_fifo(ovl);
|
||||
}
|
||||
|
||||
static void dss_setup_fifos(bool use_fifo_merge)
|
||||
static void dss_setup_fifos(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
struct omap_overlay_manager *mgr;
|
||||
|
|
@ -1031,91 +987,15 @@ static void dss_setup_fifos(bool use_fifo_merge)
|
|||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
dss_mgr_setup_fifos(mgr, use_fifo_merge);
|
||||
dss_mgr_setup_fifos(mgr);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_num_used_managers(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct mgr_priv_data *mp;
|
||||
int i;
|
||||
int enabled_mgrs;
|
||||
|
||||
enabled_mgrs = 0;
|
||||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (!mp->enabled)
|
||||
continue;
|
||||
|
||||
enabled_mgrs++;
|
||||
}
|
||||
|
||||
return enabled_mgrs;
|
||||
}
|
||||
|
||||
static int get_num_used_overlays(void)
|
||||
{
|
||||
const int num_ovls = omap_dss_get_num_overlays();
|
||||
struct omap_overlay *ovl;
|
||||
struct ovl_priv_data *op;
|
||||
struct mgr_priv_data *mp;
|
||||
int i;
|
||||
int enabled_ovls;
|
||||
|
||||
enabled_ovls = 0;
|
||||
|
||||
for (i = 0; i < num_ovls; ++i) {
|
||||
ovl = omap_dss_get_overlay(i);
|
||||
op = get_ovl_priv(ovl);
|
||||
|
||||
if (!op->enabled && !op->enabling)
|
||||
continue;
|
||||
|
||||
mp = get_mgr_priv(ovl->manager);
|
||||
|
||||
if (!mp->enabled)
|
||||
continue;
|
||||
|
||||
enabled_ovls++;
|
||||
}
|
||||
|
||||
return enabled_ovls;
|
||||
}
|
||||
|
||||
static bool get_use_fifo_merge(void)
|
||||
{
|
||||
int enabled_mgrs = get_num_used_managers();
|
||||
int enabled_ovls = get_num_used_overlays();
|
||||
|
||||
if (!dss_has_feature(FEAT_FIFO_MERGE))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* In theory the only requirement for fifomerge is enabled_ovls <= 1.
|
||||
* However, if we have two managers enabled and set/unset the fifomerge,
|
||||
* we need to set the GO bits in particular sequence for the managers,
|
||||
* and wait in between.
|
||||
*
|
||||
* This is rather difficult as new apply calls can happen at any time,
|
||||
* so we simplify the problem by requiring also that enabled_mgrs <= 1.
|
||||
* In practice this shouldn't matter, because when only one overlay is
|
||||
* enabled, most likely only one output is enabled.
|
||||
*/
|
||||
|
||||
return enabled_mgrs <= 1 && enabled_ovls <= 1;
|
||||
}
|
||||
|
||||
int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
unsigned long flags;
|
||||
int r;
|
||||
bool fifo_merge;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
|
|
@ -1133,23 +1013,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* step 1: setup fifos/fifomerge before enabling the manager */
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
dss_setup_fifos();
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait until fifo config is in */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
/* step 2: enable the manager */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (!mgr_manual_update(mgr))
|
||||
mp->updating = true;
|
||||
|
||||
|
|
@ -1174,7 +1042,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
unsigned long flags;
|
||||
bool fifo_merge;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
|
|
@ -1189,16 +1056,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|||
mp->updating = false;
|
||||
mp->enabled = false;
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
out:
|
||||
mutex_unlock(&apply_lock);
|
||||
}
|
||||
|
|
@ -1314,21 +1173,19 @@ void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
|||
const struct omap_video_timings *timings)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (mp->updating) {
|
||||
DSSERR("cannot set timings for %s: manager needs to be disabled\n",
|
||||
mgr->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dss_apply_mgr_timings(mgr, timings);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
}
|
||||
|
||||
static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
|
||||
|
|
@ -1346,7 +1203,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
|||
unsigned long flags;
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (mp->enabled) {
|
||||
DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
|
||||
|
|
@ -1354,19 +1211,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
|||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
dss_apply_mgr_lcd_config(mgr, config);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
out:
|
||||
mutex_unlock(&apply_lock);
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
}
|
||||
|
||||
int dss_ovl_set_info(struct omap_overlay *ovl,
|
||||
|
|
@ -1483,6 +1330,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
|
|||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for pending extra_info updates to ensure the ovl is disabled */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
op->channel = -1;
|
||||
|
||||
ovl->manager = NULL;
|
||||
|
|
@ -1517,7 +1371,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
unsigned long flags;
|
||||
bool fifo_merge;
|
||||
int r;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
|
@ -1543,22 +1396,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
goto err2;
|
||||
}
|
||||
|
||||
/* step 1: configure fifos/fifomerge for currently enabled ovls */
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for fifo configs to go in */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
/* step 2: enable the overlay */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
dss_setup_fifos();
|
||||
|
||||
op->enabling = false;
|
||||
dss_apply_ovl_enable(ovl, true);
|
||||
|
|
@ -1568,9 +1406,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for overlay to be enabled */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1586,7 +1421,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)
|
|||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
unsigned long flags;
|
||||
bool fifo_merge;
|
||||
int r;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
|
@ -1601,34 +1435,14 @@ int dss_ovl_disable(struct omap_overlay *ovl)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* step 1: disable the overlay */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
dss_apply_ovl_enable(ovl, false);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for the overlay to be disabled */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
/* step 2: configure fifos/fifomerge */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for fifo config to go in */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
|
@ -96,8 +94,14 @@ struct dispc_features {
|
|||
u16 pos_x, unsigned long *core_clk);
|
||||
unsigned long (*calc_core_clk) (enum omap_channel channel,
|
||||
u16 width, u16 height, u16 out_width, u16 out_height);
|
||||
u8 num_fifos;
|
||||
|
||||
/* swap GFX & WB fifos */
|
||||
bool gfx_fifo_workaround:1;
|
||||
};
|
||||
|
||||
#define DISPC_MAX_NR_FIFOS 5
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
|
|
@ -107,7 +111,9 @@ static struct {
|
|||
int irq;
|
||||
struct clk *dss_clk;
|
||||
|
||||
u32 fifo_size[MAX_DSS_OVERLAYS];
|
||||
u32 fifo_size[DISPC_MAX_NR_FIFOS];
|
||||
/* maps which plane is using a fifo. fifo-id -> plane-id */
|
||||
int fifo_assignment[DISPC_MAX_NR_FIFOS];
|
||||
|
||||
spinlock_t irq_lock;
|
||||
u32 irq_error_mask;
|
||||
|
|
@ -1063,10 +1069,10 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
|
|||
dispc_write_reg(DISPC_SIZE_MGR(channel), val);
|
||||
}
|
||||
|
||||
static void dispc_read_plane_fifo_sizes(void)
|
||||
static void dispc_init_fifos(void)
|
||||
{
|
||||
u32 size;
|
||||
int plane;
|
||||
int fifo;
|
||||
u8 start, end;
|
||||
u32 unit;
|
||||
|
||||
|
|
@ -1074,16 +1080,53 @@ static void dispc_read_plane_fifo_sizes(void)
|
|||
|
||||
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
|
||||
|
||||
for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {
|
||||
size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
|
||||
for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
|
||||
size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
|
||||
size *= unit;
|
||||
dispc.fifo_size[plane] = size;
|
||||
dispc.fifo_size[fifo] = size;
|
||||
|
||||
/*
|
||||
* By default fifos are mapped directly to overlays, fifo 0 to
|
||||
* ovl 0, fifo 1 to ovl 1, etc.
|
||||
*/
|
||||
dispc.fifo_assignment[fifo] = fifo;
|
||||
}
|
||||
|
||||
/*
|
||||
* The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
|
||||
* causes problems with certain use cases, like using the tiler in 2D
|
||||
* mode. The below hack swaps the fifos of GFX and WB planes, thus
|
||||
* giving GFX plane a larger fifo. WB but should work fine with a
|
||||
* smaller fifo.
|
||||
*/
|
||||
if (dispc.feat->gfx_fifo_workaround) {
|
||||
u32 v;
|
||||
|
||||
v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
|
||||
|
||||
v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
|
||||
v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
|
||||
v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
|
||||
v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
|
||||
|
||||
dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
|
||||
|
||||
dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
|
||||
dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
|
||||
{
|
||||
return dispc.fifo_size[plane];
|
||||
int fifo;
|
||||
u32 size = 0;
|
||||
|
||||
for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
|
||||
if (dispc.fifo_assignment[fifo] == plane)
|
||||
size += dispc.fifo_size[fifo];
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
|
||||
|
|
@ -3710,7 +3753,7 @@ static void _omap_dispc_initial_config(void)
|
|||
|
||||
dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
|
||||
|
||||
dispc_read_plane_fifo_sizes();
|
||||
dispc_init_fifos();
|
||||
|
||||
dispc_configure_burst_sizes();
|
||||
|
||||
|
|
@ -3726,6 +3769,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
|
|||
.hp_max = 256,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_24xx,
|
||||
.calc_core_clk = calc_core_clk_24xx,
|
||||
.num_fifos = 3,
|
||||
};
|
||||
|
||||
static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
|
||||
|
|
@ -3737,6 +3781,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
|
|||
.hp_max = 256,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
||||
.calc_core_clk = calc_core_clk_34xx,
|
||||
.num_fifos = 3,
|
||||
};
|
||||
|
||||
static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
|
||||
|
|
@ -3748,6 +3793,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
|
|||
.hp_max = 4096,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
||||
.calc_core_clk = calc_core_clk_34xx,
|
||||
.num_fifos = 3,
|
||||
};
|
||||
|
||||
static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
||||
|
|
@ -3759,6 +3805,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
|||
.hp_max = 4096,
|
||||
.calc_scaling = dispc_ovl_calc_scaling_44xx,
|
||||
.calc_core_clk = calc_core_clk_44xx,
|
||||
.num_fifos = 5,
|
||||
.gfx_fifo_workaround = true,
|
||||
};
|
||||
|
||||
static int __init dispc_init_features(struct device *dev)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#define DISPC_CONTROL2 0x0238
|
||||
#define DISPC_CONFIG2 0x0620
|
||||
#define DISPC_DIVISOR 0x0804
|
||||
#define DISPC_GLOBAL_BUFFER 0x0800
|
||||
#define DISPC_CONTROL3 0x0848
|
||||
#define DISPC_CONFIG3 0x084C
|
||||
|
||||
|
|
@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
|
|||
return 0x014C;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0300;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0500;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -517,6 +520,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0018;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0088;
|
||||
default:
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->driver->disable(dssdev);
|
||||
dssdev->driver->set_timings(dssdev, &t);
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -278,26 +277,12 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
|
|||
void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
int r;
|
||||
|
||||
DSSDBG("dpi_set_timings\n");
|
||||
|
||||
mutex_lock(&dpi.lock);
|
||||
|
||||
dpi.timings = *timings;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return;
|
||||
|
||||
dpi_set_mode(dssdev);
|
||||
|
||||
dispc_runtime_put();
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, timings);
|
||||
}
|
||||
|
||||
mutex_unlock(&dpi.lock);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_set_timings);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/mipi_display.h>
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -1454,6 +1453,68 @@ found:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
|
||||
unsigned long req_clk, struct dsi_clock_info *cinfo)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct dsi_clock_info cur, best;
|
||||
unsigned long dss_sys_clk, max_dss_fck, max_dsi_fck;
|
||||
unsigned long req_clkin4ddr;
|
||||
|
||||
DSSDBG("dsi_pll_calc_ddrfreq\n");
|
||||
|
||||
dss_sys_clk = clk_get_rate(dsi->sys_clk);
|
||||
|
||||
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
|
||||
|
||||
memset(&best, 0, sizeof(best));
|
||||
memset(&cur, 0, sizeof(cur));
|
||||
|
||||
cur.clkin = dss_sys_clk;
|
||||
|
||||
req_clkin4ddr = req_clk * 4;
|
||||
|
||||
for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
|
||||
cur.fint = cur.clkin / cur.regn;
|
||||
|
||||
if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
|
||||
continue;
|
||||
|
||||
/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
|
||||
for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
|
||||
unsigned long a, b;
|
||||
|
||||
a = 2 * cur.regm * (cur.clkin/1000);
|
||||
b = cur.regn;
|
||||
cur.clkin4ddr = a / b * 1000;
|
||||
|
||||
if (cur.clkin4ddr > 1800 * 1000 * 1000)
|
||||
break;
|
||||
|
||||
if (abs(cur.clkin4ddr - req_clkin4ddr) <
|
||||
abs(best.clkin4ddr - req_clkin4ddr)) {
|
||||
best = cur;
|
||||
DSSDBG("best %ld\n", best.clkin4ddr);
|
||||
}
|
||||
|
||||
if (cur.clkin4ddr == req_clkin4ddr)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found:
|
||||
best.regm_dispc = DIV_ROUND_UP(best.clkin4ddr, max_dss_fck);
|
||||
best.dsi_pll_hsdiv_dispc_clk = best.clkin4ddr / best.regm_dispc;
|
||||
|
||||
best.regm_dsi = DIV_ROUND_UP(best.clkin4ddr, max_dsi_fck);
|
||||
best.dsi_pll_hsdiv_dsi_clk = best.clkin4ddr / best.regm_dsi;
|
||||
|
||||
if (cinfo)
|
||||
*cinfo = best;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
struct dsi_clock_info *cinfo)
|
||||
{
|
||||
|
|
@ -4110,6 +4171,70 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
|
|||
}
|
||||
EXPORT_SYMBOL(omapdss_dsi_configure_pins);
|
||||
|
||||
int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
|
||||
unsigned long ddr_clk, unsigned long lp_clk)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct dsi_clock_info cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
unsigned lp_clk_div;
|
||||
unsigned long dsi_fclk;
|
||||
int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
|
||||
unsigned long pck;
|
||||
int r;
|
||||
|
||||
DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
|
||||
|
||||
mutex_lock(&dsi->lock);
|
||||
|
||||
r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk, &cinfo);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
dssdev->clocks.dsi.regn = cinfo.regn;
|
||||
dssdev->clocks.dsi.regm = cinfo.regm;
|
||||
dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
|
||||
dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
|
||||
|
||||
|
||||
dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
|
||||
lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
|
||||
|
||||
dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
|
||||
|
||||
/* pck = TxByteClkHS * datalanes * 8 / bitsperpixel */
|
||||
|
||||
pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
|
||||
|
||||
DSSDBG("finding dispc dividers for pck %lu\n", pck);
|
||||
|
||||
dispc_find_clk_divs(pck, cinfo.dsi_pll_hsdiv_dispc_clk, &dispc_cinfo);
|
||||
|
||||
dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
|
||||
dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
|
||||
|
||||
|
||||
dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
|
||||
|
||||
dssdev->clocks.dispc.channel.lcd_clk_src =
|
||||
dsi->module_id == 0 ?
|
||||
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
|
||||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
|
||||
|
||||
dssdev->clocks.dsi.dsi_fclk_src =
|
||||
dsi->module_id == 0 ?
|
||||
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
|
||||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
|
||||
|
||||
mutex_unlock(&dsi->lock);
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&dsi->lock);
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dsi_set_clocks);
|
||||
|
||||
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
|
|
@ -4740,11 +4865,6 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
|
|||
|
||||
DSSDBG("DSI init\n");
|
||||
|
||||
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
|
||||
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
|
||||
}
|
||||
|
||||
if (dsi->vdds_dsi_reg == NULL) {
|
||||
struct regulator *vdds_dsi;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include <video/omapdss.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
|
|||
|
|
@ -254,6 +254,10 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
|
|||
return false;
|
||||
}
|
||||
|
||||
int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
|
||||
struct platform_device *pdev);
|
||||
void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
|
||||
|
||||
/* overlay */
|
||||
void dss_init_overlays(struct platform_device *pdev);
|
||||
void dss_uninit_overlays(struct platform_device *pdev);
|
||||
|
|
@ -265,6 +269,9 @@ int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
|
|||
const struct omap_video_timings *mgr_timings);
|
||||
bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
|
||||
enum omap_color_mode mode);
|
||||
int dss_overlay_kobj_init(struct omap_overlay *ovl,
|
||||
struct platform_device *pdev);
|
||||
void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
|
||||
|
||||
/* DSS */
|
||||
int dss_init_platform_driver(void) __init;
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
|
|
@ -341,6 +342,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ enum dss_range_param {
|
|||
FEAT_PARAM_DSIPLL_REGM_DSI,
|
||||
FEAT_PARAM_DSIPLL_FINT,
|
||||
FEAT_PARAM_DSIPLL_LPDIV,
|
||||
FEAT_PARAM_DSI_FCK,
|
||||
FEAT_PARAM_DOWNSCALE,
|
||||
FEAT_PARAM_LINEWIDTH,
|
||||
FEAT_PARAM_MGR_WIDTH,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "ti_hdmi.h"
|
||||
|
|
@ -61,6 +63,11 @@ static struct {
|
|||
struct hdmi_ip_data ip_data;
|
||||
|
||||
struct clk *sys_clk;
|
||||
struct regulator *vdda_hdmi_dac_reg;
|
||||
|
||||
int ct_cp_hpd_gpio;
|
||||
int ls_oe_gpio;
|
||||
int hpd_gpio;
|
||||
} hdmi;
|
||||
|
||||
/*
|
||||
|
|
@ -314,12 +321,47 @@ static void hdmi_runtime_put(void)
|
|||
|
||||
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
struct gpio gpios[] = {
|
||||
{ hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
|
||||
{ hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
|
||||
{ hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
|
||||
};
|
||||
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
dss_init_hdmi_ip_ops(&hdmi.ip_data);
|
||||
|
||||
if (hdmi.vdda_hdmi_dac_reg == NULL) {
|
||||
struct regulator *reg;
|
||||
|
||||
reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
|
||||
|
||||
if (IS_ERR(reg)) {
|
||||
DSSERR("can't get VDDA_HDMI_DAC regulator\n");
|
||||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
hdmi.vdda_hdmi_dac_reg = reg;
|
||||
}
|
||||
|
||||
r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("uninit_display\n");
|
||||
|
||||
gpio_free(hdmi.ct_cp_hpd_gpio);
|
||||
gpio_free(hdmi.ls_oe_gpio);
|
||||
gpio_free(hdmi.hpd_gpio);
|
||||
}
|
||||
|
||||
static const struct hdmi_config *hdmi_find_timing(
|
||||
const struct hdmi_config *timings_arr,
|
||||
int len)
|
||||
|
|
@ -462,9 +504,19 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|||
struct omap_video_timings *p;
|
||||
unsigned long phy;
|
||||
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 1);
|
||||
|
||||
/* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
|
||||
udelay(300);
|
||||
|
||||
r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
|
||||
if (r)
|
||||
goto err_vdac_enable;
|
||||
|
||||
r = hdmi_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
goto err_runtime_get;
|
||||
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
|
|
@ -482,7 +534,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|||
r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
|
||||
if (r) {
|
||||
DSSDBG("Failed to lock PLL\n");
|
||||
goto err;
|
||||
goto err_pll_enable;
|
||||
}
|
||||
|
||||
r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
|
||||
|
|
@ -526,8 +578,13 @@ err_vid_enable:
|
|||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
err_phy_enable:
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
err:
|
||||
err_pll_enable:
|
||||
hdmi_runtime_put();
|
||||
err_runtime_get:
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
err_vdac_enable:
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
@ -539,6 +596,11 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
|
|||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
hdmi_runtime_put();
|
||||
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
}
|
||||
|
||||
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
||||
|
|
@ -570,18 +632,6 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
|
|||
if (t != NULL)
|
||||
hdmi.ip_data.cfg = *t;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
int r;
|
||||
|
||||
hdmi_power_off(dssdev);
|
||||
|
||||
r = hdmi_power_on(dssdev);
|
||||
if (r)
|
||||
DSSERR("failed to power on device\n");
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, &t->timings);
|
||||
}
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
|
|
@ -637,7 +687,6 @@ bool omapdss_hdmi_detect(void)
|
|||
|
||||
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_hdmi_data *priv = dssdev->data;
|
||||
int r = 0;
|
||||
|
||||
DSSDBG("ENTER hdmi_display_enable\n");
|
||||
|
|
@ -650,7 +699,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err0;
|
||||
}
|
||||
|
||||
hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
|
||||
hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
|
||||
|
||||
r = omap_dss_start_device(dssdev);
|
||||
if (r) {
|
||||
|
|
@ -658,26 +707,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to enable GPIO's\n");
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
||||
r = hdmi_power_on(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to power on device\n");
|
||||
goto err2;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
err1:
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
|
|
@ -693,9 +731,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
|
|||
|
||||
hdmi_power_off(dssdev);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
|
@ -873,10 +908,15 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
struct omap_dss_hdmi_data *priv = dssdev->data;
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
|
||||
continue;
|
||||
|
||||
hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
|
||||
hdmi.ls_oe_gpio = priv->ls_oe_gpio;
|
||||
hdmi.hpd_gpio = priv->hpd_gpio;
|
||||
|
||||
r = hdmi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
|
|
@ -938,8 +978,17 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __exit hdmi_remove_child(struct device *dev, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
hdmi_uninit_display(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
|
||||
{
|
||||
device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
|
||||
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
hdmi_panel_exit();
|
||||
|
|
|
|||
499
drivers/video/omap2/dss/manager-sysfs.c
Normal file
499
drivers/video/omap2/dss/manager-sysfs.c
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "MANAGER"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
|
||||
}
|
||||
|
||||
static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
mgr->device ? mgr->device->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r = 0;
|
||||
size_t len = size;
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
int match(struct omap_dss_device *dssdev, void *data)
|
||||
{
|
||||
const char *str = data;
|
||||
return sysfs_streq(dssdev->name, str);
|
||||
}
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0)
|
||||
dssdev = omap_dss_find_device((void *)buf, match);
|
||||
|
||||
if (len > 0 && dssdev == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (dssdev)
|
||||
DSSDBG("display %s found\n", dssdev->name);
|
||||
|
||||
if (mgr->device) {
|
||||
r = mgr->unset_device(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to unset display\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
if (dssdev) {
|
||||
r = mgr->set_device(mgr, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to set manager\n");
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to apply dispc config\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
put_device:
|
||||
if (dssdev)
|
||||
omap_dss_put_device(dssdev);
|
||||
|
||||
return r ? r : size;
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 color;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &color);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.default_color = color;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static const char *trans_key_type_str[] = {
|
||||
"gfx-destination",
|
||||
"video-source",
|
||||
};
|
||||
|
||||
static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
key_type = info.trans_key_type;
|
||||
BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
|
||||
for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
|
||||
key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
|
||||
if (sysfs_streq(buf, trans_key_type_str[key_type]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (key_type == ARRAY_SIZE(trans_key_type_str))
|
||||
return -EINVAL;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key_type = key_type;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 key_value;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &key_value);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key = key_value;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_show(
|
||||
struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.partial_alpha_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_store(
|
||||
struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.partial_alpha_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
if (info.cpr_enable == enable)
|
||||
return size;
|
||||
|
||||
info.cpr_enable = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d %d %d %d %d %d %d %d %d\n",
|
||||
info.cpr_coefs.rr,
|
||||
info.cpr_coefs.rg,
|
||||
info.cpr_coefs.rb,
|
||||
info.cpr_coefs.gr,
|
||||
info.cpr_coefs.gg,
|
||||
info.cpr_coefs.gb,
|
||||
info.cpr_coefs.br,
|
||||
info.cpr_coefs.bg,
|
||||
info.cpr_coefs.bb);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
struct omap_dss_cpr_coefs coefs;
|
||||
int r, i;
|
||||
s16 *arr;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
|
||||
&coefs.rr, &coefs.rg, &coefs.rb,
|
||||
&coefs.gr, &coefs.gg, &coefs.gb,
|
||||
&coefs.br, &coefs.bg, &coefs.bb) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
|
||||
coefs.gr, coefs.gg, coefs.gb,
|
||||
coefs.br, coefs.bg, coefs.bb };
|
||||
|
||||
for (i = 0; i < 9; ++i) {
|
||||
if (arr[i] < -512 || arr[i] > 511)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.cpr_coefs = coefs;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct manager_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay_manager *, char *);
|
||||
ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define MANAGER_ATTR(_name, _mode, _show, _store) \
|
||||
struct manager_attribute manager_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
|
||||
static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
|
||||
manager_display_show, manager_display_store);
|
||||
static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
|
||||
manager_default_color_show, manager_default_color_store);
|
||||
static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_type_show, manager_trans_key_type_store);
|
||||
static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_value_show, manager_trans_key_value_store);
|
||||
static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_enabled_show,
|
||||
manager_trans_key_enabled_store);
|
||||
static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_alpha_blending_enabled_show,
|
||||
manager_alpha_blending_enabled_store);
|
||||
static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_enable_show,
|
||||
manager_cpr_enable_store);
|
||||
static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_coef_show,
|
||||
manager_cpr_coef_store);
|
||||
|
||||
|
||||
static struct attribute *manager_sysfs_attrs[] = {
|
||||
&manager_attr_name.attr,
|
||||
&manager_attr_display.attr,
|
||||
&manager_attr_default_color.attr,
|
||||
&manager_attr_trans_key_type.attr,
|
||||
&manager_attr_trans_key_value.attr,
|
||||
&manager_attr_trans_key_enabled.attr,
|
||||
&manager_attr_alpha_blending_enabled.attr,
|
||||
&manager_attr_cpr_enable.attr,
|
||||
&manager_attr_cpr_coef.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->show(manager, buf);
|
||||
}
|
||||
|
||||
static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->store(manager, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops manager_sysfs_ops = {
|
||||
.show = manager_attr_show,
|
||||
.store = manager_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type manager_ktype = {
|
||||
.sysfs_ops = &manager_sysfs_ops,
|
||||
.default_attrs = manager_sysfs_attrs,
|
||||
};
|
||||
|
||||
int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
return kobject_init_and_add(&mgr->kobj, &manager_ktype,
|
||||
&pdev->dev.kobj, "manager%d", mgr->id);
|
||||
}
|
||||
|
||||
void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
kobject_del(&mgr->kobj);
|
||||
kobject_put(&mgr->kobj);
|
||||
}
|
||||
|
|
@ -36,460 +36,6 @@
|
|||
static int num_managers;
|
||||
static struct omap_overlay_manager *managers;
|
||||
|
||||
static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
|
||||
}
|
||||
|
||||
static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
mgr->device ? mgr->device->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r = 0;
|
||||
size_t len = size;
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
int match(struct omap_dss_device *dssdev, void *data)
|
||||
{
|
||||
const char *str = data;
|
||||
return sysfs_streq(dssdev->name, str);
|
||||
}
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0)
|
||||
dssdev = omap_dss_find_device((void *)buf, match);
|
||||
|
||||
if (len > 0 && dssdev == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (dssdev)
|
||||
DSSDBG("display %s found\n", dssdev->name);
|
||||
|
||||
if (mgr->device) {
|
||||
r = mgr->unset_device(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to unset display\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
if (dssdev) {
|
||||
r = mgr->set_device(mgr, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to set manager\n");
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to apply dispc config\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
put_device:
|
||||
if (dssdev)
|
||||
omap_dss_put_device(dssdev);
|
||||
|
||||
return r ? r : size;
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 color;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &color);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.default_color = color;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static const char *trans_key_type_str[] = {
|
||||
"gfx-destination",
|
||||
"video-source",
|
||||
};
|
||||
|
||||
static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
key_type = info.trans_key_type;
|
||||
BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
|
||||
for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
|
||||
key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
|
||||
if (sysfs_streq(buf, trans_key_type_str[key_type]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (key_type == ARRAY_SIZE(trans_key_type_str))
|
||||
return -EINVAL;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key_type = key_type;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 key_value;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &key_value);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key = key_value;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_show(
|
||||
struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.partial_alpha_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_store(
|
||||
struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.partial_alpha_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
if (info.cpr_enable == enable)
|
||||
return size;
|
||||
|
||||
info.cpr_enable = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d %d %d %d %d %d %d %d %d\n",
|
||||
info.cpr_coefs.rr,
|
||||
info.cpr_coefs.rg,
|
||||
info.cpr_coefs.rb,
|
||||
info.cpr_coefs.gr,
|
||||
info.cpr_coefs.gg,
|
||||
info.cpr_coefs.gb,
|
||||
info.cpr_coefs.br,
|
||||
info.cpr_coefs.bg,
|
||||
info.cpr_coefs.bb);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
struct omap_dss_cpr_coefs coefs;
|
||||
int r, i;
|
||||
s16 *arr;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
|
||||
&coefs.rr, &coefs.rg, &coefs.rb,
|
||||
&coefs.gr, &coefs.gg, &coefs.gb,
|
||||
&coefs.br, &coefs.bg, &coefs.bb) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
|
||||
coefs.gr, coefs.gg, coefs.gb,
|
||||
coefs.br, coefs.bg, coefs.bb };
|
||||
|
||||
for (i = 0; i < 9; ++i) {
|
||||
if (arr[i] < -512 || arr[i] > 511)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.cpr_coefs = coefs;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct manager_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay_manager *, char *);
|
||||
ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define MANAGER_ATTR(_name, _mode, _show, _store) \
|
||||
struct manager_attribute manager_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
|
||||
static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
|
||||
manager_display_show, manager_display_store);
|
||||
static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
|
||||
manager_default_color_show, manager_default_color_store);
|
||||
static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_type_show, manager_trans_key_type_store);
|
||||
static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_value_show, manager_trans_key_value_store);
|
||||
static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_enabled_show,
|
||||
manager_trans_key_enabled_store);
|
||||
static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_alpha_blending_enabled_show,
|
||||
manager_alpha_blending_enabled_store);
|
||||
static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_enable_show,
|
||||
manager_cpr_enable_store);
|
||||
static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_coef_show,
|
||||
manager_cpr_coef_store);
|
||||
|
||||
|
||||
static struct attribute *manager_sysfs_attrs[] = {
|
||||
&manager_attr_name.attr,
|
||||
&manager_attr_display.attr,
|
||||
&manager_attr_default_color.attr,
|
||||
&manager_attr_trans_key_type.attr,
|
||||
&manager_attr_trans_key_value.attr,
|
||||
&manager_attr_trans_key_enabled.attr,
|
||||
&manager_attr_alpha_blending_enabled.attr,
|
||||
&manager_attr_cpr_enable.attr,
|
||||
&manager_attr_cpr_coef.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->show(manager, buf);
|
||||
}
|
||||
|
||||
static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->store(manager, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops manager_sysfs_ops = {
|
||||
.show = manager_attr_show,
|
||||
.store = manager_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type manager_ktype = {
|
||||
.sysfs_ops = &manager_sysfs_ops,
|
||||
.default_attrs = manager_sysfs_attrs,
|
||||
};
|
||||
|
||||
static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
|
|
@ -561,9 +107,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
|
|||
|
||||
INIT_LIST_HEAD(&mgr->overlays);
|
||||
|
||||
r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
|
||||
&pdev->dev.kobj, "manager%d", i);
|
||||
|
||||
r = dss_manager_kobj_init(mgr, pdev);
|
||||
if (r)
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
}
|
||||
|
|
@ -577,9 +121,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < num_managers; ++i) {
|
||||
struct omap_overlay_manager *mgr = &managers[i];
|
||||
|
||||
kobject_del(&mgr->kobj);
|
||||
kobject_put(&mgr->kobj);
|
||||
dss_manager_kobj_uninit(mgr);
|
||||
}
|
||||
|
||||
kfree(managers);
|
||||
|
|
|
|||
456
drivers/video/omap2/dss/overlay-sysfs.c
Normal file
456
drivers/video/omap2/dss/overlay-sysfs.c
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "OVERLAY"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ovl->manager ? ovl->manager->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int i, r;
|
||||
struct omap_overlay_manager *mgr = NULL;
|
||||
struct omap_overlay_manager *old_mgr;
|
||||
int len = size;
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0) {
|
||||
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
|
||||
if (sysfs_streq(buf, mgr->name))
|
||||
break;
|
||||
|
||||
mgr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0 && mgr == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mgr)
|
||||
DSSDBG("manager %s found\n", mgr->name);
|
||||
|
||||
if (mgr == ovl->manager)
|
||||
return size;
|
||||
|
||||
old_mgr = ovl->manager;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* detach old manager */
|
||||
if (old_mgr) {
|
||||
r = ovl->unset_manager(ovl);
|
||||
if (r) {
|
||||
DSSERR("detach failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = old_mgr->apply(old_mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mgr) {
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r) {
|
||||
DSSERR("Failed to attach overlay\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dispc_runtime_put();
|
||||
|
||||
return size;
|
||||
|
||||
err:
|
||||
dispc_runtime_put();
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.width, info.height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.pos_x, info.pos_y);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pos_x = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.pos_y = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.out_width, info.out_height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.out_width = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.out_height = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (enable)
|
||||
r = ovl->enable(ovl);
|
||||
else
|
||||
r = ovl->disable(ovl);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.global_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.global_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.pre_mult_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pre_mult_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 zorder;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &zorder);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.zorder = zorder;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct overlay_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay *, char *);
|
||||
ssize_t (*store)(struct omap_overlay *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define OVERLAY_ATTR(_name, _mode, _show, _store) \
|
||||
struct overlay_attribute overlay_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
|
||||
static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
|
||||
overlay_manager_show, overlay_manager_store);
|
||||
static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
|
||||
static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
|
||||
static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
|
||||
overlay_position_show, overlay_position_store);
|
||||
static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
|
||||
overlay_output_size_show, overlay_output_size_store);
|
||||
static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
|
||||
overlay_enabled_show, overlay_enabled_store);
|
||||
static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_global_alpha_show, overlay_global_alpha_store);
|
||||
static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_pre_mult_alpha_show,
|
||||
overlay_pre_mult_alpha_store);
|
||||
static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
|
||||
overlay_zorder_show, overlay_zorder_store);
|
||||
|
||||
static struct attribute *overlay_sysfs_attrs[] = {
|
||||
&overlay_attr_name.attr,
|
||||
&overlay_attr_manager.attr,
|
||||
&overlay_attr_input_size.attr,
|
||||
&overlay_attr_screen_width.attr,
|
||||
&overlay_attr_position.attr,
|
||||
&overlay_attr_output_size.attr,
|
||||
&overlay_attr_enabled.attr,
|
||||
&overlay_attr_global_alpha.attr,
|
||||
&overlay_attr_pre_mult_alpha.attr,
|
||||
&overlay_attr_zorder.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->show(overlay, buf);
|
||||
}
|
||||
|
||||
static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->store(overlay, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops overlay_sysfs_ops = {
|
||||
.show = overlay_attr_show,
|
||||
.store = overlay_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type overlay_ktype = {
|
||||
.sysfs_ops = &overlay_sysfs_ops,
|
||||
.default_attrs = overlay_sysfs_attrs,
|
||||
};
|
||||
|
||||
int dss_overlay_kobj_init(struct omap_overlay *ovl,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
|
||||
&pdev->dev.kobj, "overlay%d", ovl->id);
|
||||
}
|
||||
|
||||
void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
|
||||
{
|
||||
kobject_del(&ovl->kobj);
|
||||
kobject_put(&ovl->kobj);
|
||||
}
|
||||
|
|
@ -26,13 +26,11 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -40,417 +38,6 @@
|
|||
static int num_overlays;
|
||||
static struct omap_overlay *overlays;
|
||||
|
||||
static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ovl->manager ? ovl->manager->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int i, r;
|
||||
struct omap_overlay_manager *mgr = NULL;
|
||||
struct omap_overlay_manager *old_mgr;
|
||||
int len = size;
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0) {
|
||||
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
|
||||
if (sysfs_streq(buf, mgr->name))
|
||||
break;
|
||||
|
||||
mgr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0 && mgr == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mgr)
|
||||
DSSDBG("manager %s found\n", mgr->name);
|
||||
|
||||
if (mgr == ovl->manager)
|
||||
return size;
|
||||
|
||||
old_mgr = ovl->manager;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* detach old manager */
|
||||
if (old_mgr) {
|
||||
r = ovl->unset_manager(ovl);
|
||||
if (r) {
|
||||
DSSERR("detach failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = old_mgr->apply(old_mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mgr) {
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r) {
|
||||
DSSERR("Failed to attach overlay\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dispc_runtime_put();
|
||||
|
||||
return size;
|
||||
|
||||
err:
|
||||
dispc_runtime_put();
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.width, info.height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.pos_x, info.pos_y);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pos_x = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.pos_y = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.out_width, info.out_height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.out_width = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.out_height = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (enable)
|
||||
r = ovl->enable(ovl);
|
||||
else
|
||||
r = ovl->disable(ovl);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.global_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.global_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.pre_mult_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pre_mult_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 zorder;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &zorder);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.zorder = zorder;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct overlay_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay *, char *);
|
||||
ssize_t (*store)(struct omap_overlay *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define OVERLAY_ATTR(_name, _mode, _show, _store) \
|
||||
struct overlay_attribute overlay_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
|
||||
static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
|
||||
overlay_manager_show, overlay_manager_store);
|
||||
static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
|
||||
static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
|
||||
static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
|
||||
overlay_position_show, overlay_position_store);
|
||||
static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
|
||||
overlay_output_size_show, overlay_output_size_store);
|
||||
static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
|
||||
overlay_enabled_show, overlay_enabled_store);
|
||||
static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_global_alpha_show, overlay_global_alpha_store);
|
||||
static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_pre_mult_alpha_show,
|
||||
overlay_pre_mult_alpha_store);
|
||||
static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
|
||||
overlay_zorder_show, overlay_zorder_store);
|
||||
|
||||
static struct attribute *overlay_sysfs_attrs[] = {
|
||||
&overlay_attr_name.attr,
|
||||
&overlay_attr_manager.attr,
|
||||
&overlay_attr_input_size.attr,
|
||||
&overlay_attr_screen_width.attr,
|
||||
&overlay_attr_position.attr,
|
||||
&overlay_attr_output_size.attr,
|
||||
&overlay_attr_enabled.attr,
|
||||
&overlay_attr_global_alpha.attr,
|
||||
&overlay_attr_pre_mult_alpha.attr,
|
||||
&overlay_attr_zorder.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->show(overlay, buf);
|
||||
}
|
||||
|
||||
static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->store(overlay, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops overlay_sysfs_ops = {
|
||||
.show = overlay_attr_show,
|
||||
.store = overlay_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type overlay_ktype = {
|
||||
.sysfs_ops = &overlay_sysfs_ops,
|
||||
.default_attrs = overlay_sysfs_attrs,
|
||||
};
|
||||
|
||||
int omap_dss_get_num_overlays(void)
|
||||
{
|
||||
return num_overlays;
|
||||
|
|
@ -512,9 +99,7 @@ void dss_init_overlays(struct platform_device *pdev)
|
|||
ovl->supported_modes =
|
||||
dss_feat_get_supported_color_modes(ovl->id);
|
||||
|
||||
r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
|
||||
&pdev->dev.kobj, "overlay%d", i);
|
||||
|
||||
r = dss_overlay_kobj_init(ovl, pdev);
|
||||
if (r)
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
}
|
||||
|
|
@ -595,9 +180,7 @@ void dss_uninit_overlays(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < num_overlays; ++i) {
|
||||
struct omap_overlay *ovl = &overlays[i];
|
||||
|
||||
kobject_del(&ovl->kobj);
|
||||
kobject_put(&ovl->kobj);
|
||||
dss_overlay_kobj_uninit(ovl);
|
||||
}
|
||||
|
||||
kfree(overlays);
|
||||
|
|
|
|||
|
|
@ -939,7 +939,6 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
|
|||
static int __init rfbi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,17 +152,7 @@ EXPORT_SYMBOL(omapdss_sdi_display_disable);
|
|||
void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
int r;
|
||||
|
||||
sdi.timings = *timings;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
omapdss_sdi_display_disable(dssdev);
|
||||
|
||||
r = omapdss_sdi_display_enable(dssdev);
|
||||
if (r)
|
||||
DSSERR("failed to set new timings\n");
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_set_timings);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -565,19 +564,6 @@ void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
|
|||
|
||||
venc.timings = *timings;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
int r;
|
||||
|
||||
/* turn the venc off and on to get new timings to use */
|
||||
venc_power_off(dssdev);
|
||||
|
||||
r = venc_power_on(dssdev);
|
||||
if (r)
|
||||
DSSERR("failed to power on VENC\n");
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, timings);
|
||||
}
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1592,6 +1592,20 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void omapfb_clear_fb(struct fb_info *fbi)
|
||||
{
|
||||
const struct fb_fillrect rect = {
|
||||
.dx = 0,
|
||||
.dy = 0,
|
||||
.width = fbi->var.xres_virtual,
|
||||
.height = fbi->var.yres_virtual,
|
||||
.color = 0,
|
||||
.rop = ROP_COPY,
|
||||
};
|
||||
|
||||
cfb_fillrect(fbi, &rect);
|
||||
}
|
||||
|
||||
int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
|
@ -1661,6 +1675,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
|||
goto err;
|
||||
}
|
||||
|
||||
omapfb_clear_fb(fbi);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
omapfb_free_fbmem(fbi);
|
||||
|
|
@ -1972,6 +1988,16 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
struct fb_info *fbi = fbdev->fbs[i];
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
if (ofbi->region->size == 0)
|
||||
continue;
|
||||
|
||||
omapfb_clear_fb(fbi);
|
||||
}
|
||||
|
||||
/* Enable fb0 */
|
||||
if (fbdev->num_fbs > 0) {
|
||||
struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <asm/setup.h>
|
||||
|
||||
#include <plat/vram.h>
|
||||
#include <plat/dma.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
|
||||
|
|
@ -250,59 +249,6 @@ int omap_vram_reserve(unsigned long paddr, size_t size)
|
|||
}
|
||||
EXPORT_SYMBOL(omap_vram_reserve);
|
||||
|
||||
static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
|
||||
{
|
||||
struct completion *compl = data;
|
||||
complete(compl);
|
||||
}
|
||||
|
||||
static int _omap_vram_clear(u32 paddr, unsigned pages)
|
||||
{
|
||||
struct completion compl;
|
||||
unsigned elem_count;
|
||||
unsigned frame_count;
|
||||
int r;
|
||||
int lch;
|
||||
|
||||
init_completion(&compl);
|
||||
|
||||
r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
|
||||
_omap_vram_dma_cb,
|
||||
&compl, &lch);
|
||||
if (r) {
|
||||
pr_err("VRAM: request_dma failed for memory clear\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
elem_count = pages * PAGE_SIZE / 4;
|
||||
frame_count = 1;
|
||||
|
||||
omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
|
||||
elem_count, frame_count,
|
||||
OMAP_DMA_SYNC_ELEMENT,
|
||||
0, 0);
|
||||
|
||||
omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
|
||||
paddr, 0, 0);
|
||||
|
||||
omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
|
||||
|
||||
omap_start_dma(lch);
|
||||
|
||||
if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
|
||||
omap_stop_dma(lch);
|
||||
pr_err("VRAM: dma timeout while clearing memory\n");
|
||||
r = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
err:
|
||||
omap_free_dma(lch);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
|
|
@ -337,8 +283,6 @@ found:
|
|||
|
||||
*paddr = start;
|
||||
|
||||
_omap_vram_clear(start, pages);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ enum omap_plane {
|
|||
OMAP_DSS_VIDEO1 = 1,
|
||||
OMAP_DSS_VIDEO2 = 2,
|
||||
OMAP_DSS_VIDEO3 = 3,
|
||||
OMAP_DSS_WB = 4,
|
||||
};
|
||||
|
||||
enum omap_channel {
|
||||
|
|
@ -605,6 +606,8 @@ struct omap_dss_device {
|
|||
|
||||
struct omap_dss_hdmi_data
|
||||
{
|
||||
int ct_cp_hpd_gpio;
|
||||
int ls_oe_gpio;
|
||||
int hpd_gpio;
|
||||
};
|
||||
|
||||
|
|
@ -736,6 +739,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
|
|||
void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
|
||||
int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
|
||||
const struct omap_dsi_pin_config *pin_cfg);
|
||||
int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
|
||||
unsigned long ddr_clk, unsigned long lp_clk);
|
||||
|
||||
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue