Commit 60548a2b authored by Tomi Valkeinen's avatar Tomi Valkeinen

Merge output work from Archit

The series removes bunch of dssdev references from the omapdss output drivers.
This is made to let us move to a common panel framework later, and also allows
us to implement OMAP's writeback support, which has been proven difficult with
the current output drivers.

OMAPDSS: APPLY: Constify timings argument in dss_mgr_set_timings
OMAPDSS: DPI: Add locking for DPI interface
OMAPDSS: Displays: Add locking in generic DPI panel driver
OMAPDSS: DPI: Maintain our own timings field in driver data
OMAPDSS: DPI displays: Take care of panel timings in the driver itself
OMAPDSS: DSI: Maintain own copy of timings in driver data
OMAPDSS: DSI: Add function to set panel size for command mode panels
OMAPDSS: DSI: Update manager timings on a manual update
OMAPDSS: HDMI: Use our own omap_video_timings field when setting interface timings
OMAPDSS: HDMI: Add locking for hdmi interface set timing functions
OMAPDSS: SDI: Create a function to set timings
OMAPDSS: SDI: Maintain our own timings field in driver data
OMAPDSS: VENC: Split VENC into interface and panel driver
OMAPDSS: VENC: Maintain our own timings field in driver data
OMAPDSS: RFBI: Remove partial update support
OMAPDSS: RFBI: Add function to set panel size
OMAPDSS: DSI: Maintain copy of pixel format in driver data
OMAPDSS: RFBI: Maintain copy of pixel size in driver data
OMAPDSS: RFBI: Maintain copy of number of data lines in driver data
OMAPDSS: DPI: Maintain copy of number of data lines in driver data
OMAPDSS: SDI: Maintain copy of data pairs in driver data
OMAPDSS: DSI: Maintain copy of operation mode in driver data
OMAPDSS: DSI: Rename dsi_videomode_data to dsi_videomode_timings
OMAPDSS: DSI: Maintain copy of video mode timings in driver data
OMAPDSS: RFBI: Maitain copy of rfbi timings in driver data
OMAPDSS: VENC: Maintain copy of venc type in driver data
OMAPDSS: VENC: Maintian copy of video output polarity info in private data
parents a2496dc9 89e71956
......@@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
mutex_lock(&md->mutex);
omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
r = omapdss_sdi_display_enable(dssdev);
if (r) {
pr_err("%s sdi enable failed\n", __func__);
......@@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)
static void acx_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
int r;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
omapdss_sdi_display_disable(dssdev);
omapdss_sdi_set_timings(dssdev, timings);
dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
r = omapdss_sdi_display_enable(dssdev);
if (r)
dev_err(&dssdev->dev, "%s enable failed\n", __func__);
}
}
static int acx_panel_check_timings(struct omap_dss_device *dssdev,
......
......@@ -545,6 +545,8 @@ struct panel_drv_data {
struct omap_dss_device *dssdev;
struct panel_config *panel_config;
struct mutex lock;
};
static inline struct panel_generic_dpi_data
......@@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
......@@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
drv_data->dssdev = dssdev;
drv_data->panel_config = panel_config;
mutex_init(&drv_data->lock);
dev_set_drvdata(&dssdev->dev, drv_data);
return 0;
......@@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
{
int r = 0;
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&drv_data->lock);
r = generic_dpi_panel_power_on(dssdev);
if (r)
return r;
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
err:
mutex_unlock(&drv_data->lock);
return 0;
return r;
}
static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
mutex_lock(&drv_data->lock);
generic_dpi_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
mutex_unlock(&drv_data->lock);
}
static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
mutex_lock(&drv_data->lock);
generic_dpi_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&drv_data->lock);
return 0;
}
static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
{
int r = 0;
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&drv_data->lock);
r = generic_dpi_panel_power_on(dssdev);
if (r)
return r;
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return 0;
err:
mutex_unlock(&drv_data->lock);
return r;
}
static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
dpi_set_timings(dssdev, timings);
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
mutex_lock(&drv_data->lock);
omapdss_dpi_set_timings(dssdev, timings);
dssdev->panel.timings = *timings;
mutex_unlock(&drv_data->lock);
}
static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
mutex_lock(&drv_data->lock);
*timings = dssdev->panel.timings;
mutex_unlock(&drv_data->lock);
}
static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
return dpi_check_timings(dssdev, timings);
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&drv_data->lock);
r = dpi_check_timings(dssdev, timings);
mutex_unlock(&drv_data->lock);
return r;
}
static struct omap_dss_driver dpi_driver = {
......@@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {
.resume = generic_dpi_panel_resume,
.set_timings = generic_dpi_panel_set_timings,
.get_timings = generic_dpi_panel_get_timings,
.check_timings = generic_dpi_panel_check_timings,
.driver = {
......
......@@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
......
......@@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
BLIZZARD_SRC_WRITE_LCD :
BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
omap_rfbi_configure(dssdev, 16, 8);
omapdss_rfbi_set_pixel_size(dssdev, 16);
omapdss_rfbi_set_data_lines(dssdev, 8);
omap_rfbi_configure(dssdev);
blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
omap_rfbi_configure(dssdev, 16, 16);
omapdss_rfbi_set_pixel_size(dssdev, 16);
omapdss_rfbi_set_data_lines(dssdev, 16);
omap_rfbi_configure(dssdev);
}
static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
......@@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
goto err_plat_en;
}
omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);
omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
r = omapdss_rfbi_display_enable(dssdev);
if (r)
goto err_rfbi_en;
......@@ -625,17 +637,25 @@ static int n8x0_panel_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
u16 dw, dh;
dev_dbg(&dssdev->dev, "update\n");
dw = dssdev->panel.timings.x_res;
dh = dssdev->panel.timings.y_res;
if (x != 0 || y != 0 || w != dw || h != dh) {
dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
x, y, w, h);
return -EINVAL;
}
mutex_lock(&ddata->lock);
rfbi_bus_lock();
omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
blizzard_ctrl_setup_update(dssdev, x, y, w, h);
omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
omap_rfbi_update(dssdev, update_done, NULL);
mutex_unlock(&ddata->lock);
......
......@@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
......
......@@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
* then only i2c commands can be successfully sent to dpp2600
*/
msleep(1000);
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r) {
dev_err(&dssdev->dev, "failed to enable DPI\n");
......
......@@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
......
......@@ -1060,6 +1060,11 @@ static int taal_power_on(struct omap_dss_device *dssdev)
goto err0;
};
omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);
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_display_enable(dssdev);
if (r) {
dev_err(&dssdev->dev, "failed to enable DSI\n");
......@@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)
static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
u16 dw, dh;
int r;
dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
......@@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
goto err;
}
if (rotate == 0 || rotate == 2) {
dw = dssdev->panel.timings.x_res;
dh = dssdev->panel.timings.y_res;
} else {
dw = dssdev->panel.timings.y_res;
dh = dssdev->panel.timings.x_res;
}
omapdss_dsi_set_size(dssdev, dw, dh);
td->rotate = rotate;
dsi_bus_unlock(dssdev);
......
......@@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
......@@ -231,7 +234,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
dpi_set_timings(dssdev, timings);
omapdss_dpi_set_timings(dssdev, timings);
dssdev->panel.timings = *timings;
mutex_unlock(&ddata->lock);
}
......
......@@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
......@@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
dpi_set_timings(dssdev, timings);
omapdss_dpi_set_timings(dssdev, timings);
dssdev->panel.timings = *timings;
}
static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
......
......@@ -3,7 +3,7 @@ omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
manager.o overlay.o apply.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
......
......@@ -1302,7 +1302,7 @@ int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
}
static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
struct omap_video_timings *timings)
const struct omap_video_timings *timings)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
......@@ -1311,7 +1311,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
}
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
struct omap_video_timings *timings)
const struct omap_video_timings *timings)
{
unsigned long flags;
......
......@@ -39,7 +39,11 @@ static struct {
struct regulator *vdds_dsi_reg;
struct platform_device *dsidev;
struct mutex lock;
struct omap_video_timings timings;
struct dss_lcd_mgr_config mgr_config;
int data_lines;
} dpi;
static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
......@@ -121,7 +125,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
static int dpi_set_mode(struct omap_dss_device *dssdev)
{
struct omap_video_timings *t = &dssdev->panel.timings;
struct omap_video_timings *t = &dpi.timings;
int lck_div = 0, pck_div = 0;
unsigned long fck = 0;
unsigned long pck;
......@@ -158,7 +162,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
dpi.mgr_config.stallmode = false;
dpi.mgr_config.fifohandcheck = false;
dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines;
dpi.mgr_config.video_port_width = dpi.data_lines;
dpi.mgr_config.lcden_sig_polarity = 0;
......@@ -169,14 +173,18 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
{
int r;
mutex_lock(&dpi.lock);
if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
DSSERR("no VDSS_DSI regulator\n");
return -ENODEV;
r = -ENODEV;
goto err_no_reg;
}
if (dssdev->manager == NULL) {
DSSERR("failed to enable display: no manager\n");
return -ENODEV;
r = -ENODEV;
goto err_no_mgr;
}
r = omap_dss_start_device(dssdev);
......@@ -217,6 +225,8 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_mgr_enable;
mutex_unlock(&dpi.lock);
return 0;
err_mgr_enable:
......@@ -234,12 +244,17 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
err_reg_enable:
omap_dss_stop_device(dssdev);
err_start_dev:
err_no_mgr:
err_no_reg:
mutex_unlock(&dpi.lock);
return r;
}
EXPORT_SYMBOL(omapdss_dpi_display_enable);
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
{
mutex_lock(&dpi.lock);
dss_mgr_disable(dssdev->manager);
if (dpi_use_dsi_pll(dssdev)) {
......@@ -254,16 +269,22 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
regulator_disable(dpi.vdds_dsi_reg);
omap_dss_stop_device(dssdev);
mutex_unlock(&dpi.lock);
}
EXPORT_SYMBOL(omapdss_dpi_display_disable);
void dpi_set_timings(struct omap_dss_device *dssdev,
void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
int r;
DSSDBG("dpi_set_timings\n");
dssdev->panel.timings = *timings;
mutex_lock(&dpi.lock);
dpi.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
r = dispc_runtime_get();
if (r)
......@@ -275,8 +296,10 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
} else {
dss_mgr_set_timings(dssdev->manager, timings);
}
mutex_unlock(&dpi.lock);
}
EXPORT_SYMBOL(dpi_set_timings);
EXPORT_SYMBOL(omapdss_dpi_set_timings);
int dpi_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
......@@ -325,6 +348,16 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
}
EXPORT_SYMBOL(dpi_check_timings);
void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
{
mutex_lock(&dpi.lock);
dpi.data_lines = data_lines;
mutex_unlock(&dpi.lock);
}
EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
static int __init dpi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
......@@ -377,6 +410,8 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
static int __init omap_dpi_probe(struct platform_device *pdev)
{
mutex_init(&dpi.lock);
dpi_probe_pdata(pdev);
return 0;
......
This diff is collapsed.
......@@ -144,7 +144,7 @@ static void dss_restore_context(void)
#undef SR
#undef RR
void dss_sdi_init(u8 datapairs)
void dss_sdi_init(int datapairs)
{
u32 l;
......
......@@ -206,7 +206,7 @@ int dss_mgr_set_device(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev);
int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
struct omap_video_timings *timings);
const struct omap_video_timings *timings);
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
const struct dss_lcd_mgr_config *config);
const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
......@@ -279,7 +279,7 @@ void dss_dump_clocks(struct seq_file *s);
void dss_debug_dump_clocks(struct seq_file *s);
#endif
void dss_sdi_init(u8 datapairs);
void dss_sdi_init(int datapairs);
int dss_sdi_enable(void);
void dss_sdi_disable(void);
......@@ -469,6 +469,20 @@ static inline unsigned long venc_get_pixel_clock(void)
return 0;
}
#endif
int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
void omapdss_venc_set_type(struct omap_dss_device *dssdev,
enum omap_dss_venc_type type);
void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
bool invert_polarity);
int venc_panel_init(void);
void venc_panel_exit(void);
/* HDMI */
#ifdef CONFIG_OMAP4_DSS_HDMI
......@@ -484,7 +498,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
#endif
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int omapdss_hdmi_read_edid(u8 *buf, int len);
......
......@@ -459,7 +459,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
int r;
const struct hdmi_config *timing;
struct omap_video_timings *p;
unsigned long phy;
......@@ -469,22 +468,10 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dss_mgr_disable(dssdev->manager);
p = &dssdev->panel.timings;
p = &hdmi.ip_data.cfg.timings;
DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);
DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
timing = hdmi_get_timings();
if (timing == NULL) {
/* HDMI code 4 corresponds to 640 * 480 VGA */
hdmi.ip_data.cfg.cm.code = 4;
/* DVI mode 1 corresponds to HDMI 0 to DVI */
hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
hdmi.ip_data.cfg = vesa_timings[0];
} else {
hdmi.ip_data.cfg = *timing;
}
phy = p->pixel_clock;
hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
......@@ -521,7 +508,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dispc_enable_gamma_table(0);
/* tv size */
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
dss_mgr_set_timings(dssdev->manager, p);
r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
if (r)
......@@ -568,13 +555,20 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
}
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct hdmi_cm cm;
const struct hdmi_config *t;
mutex_lock(&hdmi.lock);
cm = hdmi_get_code(&dssdev->panel.timings);
hdmi.ip_data.cfg.cm.code = cm.code;
hdmi.ip_data.cfg.cm.mode = cm.mode;
cm = hdmi_get_code(timings);
hdmi.ip_data.cfg.cm = cm;
t = hdmi_get_timings();
if (t != NULL)
hdmi.ip_data.cfg = *t;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
int r;
......@@ -585,8 +579,10 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
if (r)
DSSERR("failed to power on device\n");
} else {
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
dss_mgr_set_timings(dssdev->manager, &t->timings);
}
mutex_unlock(&hdmi.lock);
}
static void hdmi_dump_regs(struct seq_file *s)
......@@ -930,6 +926,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
hdmi.ip_data.phy_offset = HDMI_PHY;
mutex_init(&hdmi.ip_data.lock);
hdmi_panel_init();
......
......@@ -41,17 +41,32 @@ static struct {
static int hdmi_panel_probe(struct omap_dss_device *dssdev)
{
/* Initialize default timings to VGA in DVI mode */
const struct omap_video_timings default_timings = {
.x_res = 640,
.y_res = 480,
.pixel_clock = 25175,
.hsw = 96,
.hfp = 16,
.hbp = 48,
.vsw = 2,
.vfp = 11,
.vbp = 31,
.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
.interlace = false,
};
DSSDBG("ENTER hdmi_panel_probe\n");
dssdev->panel.timings = (struct omap_video_timings)
{ 640, 480, 25175, 96, 16, 48, 2, 11, 31,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false,
};
dssdev->panel.timings = default_timings;
DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);
return 0;
}
......@@ -228,6 +243,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
goto err;
}
omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
r = omapdss_hdmi_display_enable(dssdev);
if (r) {
DSSERR("failed to power on\n");
......@@ -336,8 +353,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
*/
hdmi_panel_audio_disable(dssdev);
omapdss_hdmi_display_set_timing(dssdev, timings);
dssdev->panel.timings = *timings;
omapdss_hdmi_display_set_timing(dssdev);
mutex_unlock(&hdmi.lock);
}
......
......@@ -111,6 +111,11 @@ static struct {
struct omap_dss_device *dssdev[2];
struct semaphore bus_lock;
struct omap_video_timings timings;
int pixel_size;
int data_lines;
struct rfbi_timings intf_timings;
} rfbi;
static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
......@@ -300,28 +305,20 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
}
EXPORT_SYMBOL(omap_rfbi_write_pixels);
static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
u16 height, void (*callback)(void *data), void *data)
static int rfbi_transfer_area(struct omap_dss_device *dssdev,
void (*callback)(void *data), void *data)
{
u32 l;
int r;
struct omap_video_timings timings = {
.hsw = 1,
.hfp = 1,
.hbp = 1,
.vsw = 1,
.vfp = 0,
.vbp = 0,
.x_res = width,
.y_res = height,
};
u16 width = rfbi.timings.x_res;
u16 height = rfbi.timings.y_res;
/*BUG_ON(callback == 0);*/
BUG_ON(rfbi.framedone_callback != NULL);
DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
dss_mgr_set_timings(dssdev->manager, &timings);
dss_mgr_set_timings(dssdev->manager, &rfbi.timings);
r = dss_mgr_enable(dssdev->manager);
if (r)
......@@ -770,62 +767,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
return 0;
}
int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
int data_lines)
int omap_rfbi_configure(struct omap_dss_device *dssdev)
{
return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
rfbi.data_lines);
}
EXPORT_SYMBOL(omap_rfbi_configure);
int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
u16 *x, u16 *y, u16 *w, u16 *h)
int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
void *data)
{
u16 dw, dh;
struct omap_video_timings timings = {
.hsw = 1,
.hfp = 1,
.hbp = 1,
.vsw = 1,
.vfp = 0,
.vbp = 0,
.x_res = *w,
.y_res = *h,
};
dssdev->driver->get_resolution(dssdev, &dw, &dh);
if (*x > dw || *y > dh)
return -EINVAL;
if (*x + *w > dw)
return -EINVAL;
if (*y + *h > dh)
return -EINVAL;
if (*w == 1)
return -EINVAL;
if (*w == 0 || *h == 0)
return -EINVAL;
dss_mgr_set_timings(dssdev->manager, &timings);
return rfbi_transfer_area(dssdev, callback, data);
}
EXPORT_SYMBOL(omap_rfbi_update);
return 0;
void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
{
rfbi.timings.x_res = w;
rfbi.timings.y_res = h;
}
EXPORT_SYMBOL(omap_rfbi_prepare_update);
EXPORT_SYMBOL(omapdss_rfbi_set_size);
int omap_rfbi_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h,
void (*callback)(void *), void *data)
void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
{
int r;
rfbi.pixel_size = pixel_size;
}
EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
r = rfbi_transfer_area(dssdev, w, h, callback, data);
void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
{
rfbi.data_lines = data_lines;
}
EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
return r;
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings)
{
rfbi.intf_timings = *timings;
}
EXPORT_SYMBOL(omap_rfbi_update);
EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
static void rfbi_dump_regs(struct seq_file *s)
{
......@@ -877,10 +857,31 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
/* Do we need fifohandcheck for RFBI? */
mgr_config.fifohandcheck = false;
mgr_config.video_port_width = dssdev->ctrl.pixel_size;
mgr_config.video_port_width = rfbi.pixel_size;
mgr_config.lcden_sig_polarity = 0;
dss_mgr_set_lcd_config(dssdev->manager, &mgr_config);
/*
* Set rfbi.timings with default values, the x_res and y_res fields
* are expected to be already configured by the panel driver via
* omapdss_rfbi_set_size()
*/
rfbi.timings.hsw = 1;
rfbi.timings.hfp = 1;
rfbi.timings.hbp = 1;
rfbi.timings.vsw = 1;
rfbi.timings.vfp = 0;
rfbi.timings.vbp = 0;
rfbi.timings.interlace = false;
rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
dss_mgr_set_timings(dssdev->manager, &rfbi.timings);
}
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
......@@ -911,13 +912,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
rfbi_config_lcd_manager(dssdev);
rfbi_configure(dssdev->phy.rfbi.channel,
dssdev->ctrl.pixel_size,
dssdev->phy.rfbi.data_lines);
rfbi_set_timings(dssdev->phy.rfbi.channel,
&dssdev->ctrl.rfbi_timings);
rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
rfbi.data_lines);
rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
return 0;
err1:
......
......@@ -34,6 +34,8 @@ static struct {
struct regulator *vdds_sdi_reg;
struct dss_lcd_mgr_config mgr_config;
struct omap_video_timings timings;
int datapairs;
} sdi;
static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
......@@ -51,7 +53,7 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
{
struct omap_video_timings *t = &dssdev->panel.timings;
struct omap_video_timings *t = &sdi.timings;
struct dss_clock_info dss_cinfo;
struct dispc_clock_info dispc_cinfo;
unsigned long pck;
......@@ -77,8 +79,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
goto err_get_dispc;
/* 15.5.9.1.2 */
dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
if (r)
......@@ -105,7 +107,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
sdi_config_lcd_manager(dssdev);
dss_sdi_init(dssdev->phy.sdi.datapairs);
dss_sdi_init(sdi.datapairs);
r = dss_sdi_enable();
if (r)
goto err_sdi_enable;
......@@ -146,6 +149,29 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
}
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);
void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
{
sdi.datapairs = datapairs;
}
EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
static int __init sdi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("SDI init\n");
......
......@@ -300,6 +300,10 @@ static struct {
struct regulator *vdda_dac_reg;
struct clk *tv_dac_clk;
struct omap_video_timings timings;
enum omap_dss_venc_type type;
bool invert_polarity;
} venc;
static inline void venc_write_reg(int idx, u32 val)
......@@ -427,48 +431,48 @@ static int venc_power_on(struct omap_dss_device *dssdev)
u32 l;
int r;
r = venc_runtime_get();
if (r)
goto err0;
venc_reset();
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
venc_write_config(venc_timings_to_config(&venc.timings));
dss_set_venc_output(dssdev->phy.venc.type);
dss_set_venc_output(venc.type);
dss_set_dac_pwrdn_bgz(1);
l = 0;
if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
l |= 1 << 1;
else /* S-Video */
l |= (1 << 0) | (1 << 2);
if (dssdev->phy.venc.invert_polarity == false)
if (venc.invert_polarity == false)
l |= 1 << 3;
venc_write_reg(VENC_OUTPUT_CONTROL, l);
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
dss_mgr_set_timings(dssdev->manager, &venc.timings);
r = regulator_enable(venc.vdda_dac_reg);
if (r)
goto err;
if (dssdev->platform_enable)
dssdev->platform_enable(dssdev);
goto err1;
r = dss_mgr_enable(dssdev->manager);
if (r)
goto err;
goto err2;
return 0;
err:
err2:
regulator_disable(venc.vdda_dac_reg);
err1:
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
dss_set_dac_pwrdn_bgz(0);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
regulator_disable(venc.vdda_dac_reg);
venc_runtime_put();
err0:
return r;
}
......@@ -479,10 +483,9 @@ static void venc_power_off(struct omap_dss_device *dssdev)
dss_mgr_disable(dssdev->manager);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
regulator_disable(venc.vdda_dac_reg);
venc_runtime_put();
}
unsigned long venc_get_pixel_clock(void)
......@@ -491,170 +494,94 @@ unsigned long venc_get_pixel_clock(void)
return 13500000;
}
static ssize_t display_output_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
const char *ret;
switch (dssdev->phy.venc.type) {
case OMAP_DSS_VENC_TYPE_COMPOSITE:
ret = "composite";
break;
case OMAP_DSS_VENC_TYPE_SVIDEO:
ret = "svideo";
break;
default:
return -EINVAL;
}
return snprintf(buf, PAGE_SIZE, "%s\n", ret);
}
int r;
static ssize_t display_output_type_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
enum omap_dss_venc_type new_type;
if (sysfs_streq("composite", buf))
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
else if (sysfs_streq("svideo", buf))
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
else
return -EINVAL;
DSSDBG("venc_display_enable\n");
mutex_lock(&venc.venc_lock);
if (dssdev->phy.venc.type != new_type) {
dssdev->phy.venc.type = new_type;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
venc_power_off(dssdev);
venc_power_on(dssdev);
}
if (dssdev->manager == NULL) {
DSSERR("Failed to enable display: no manager\n");
r = -ENODEV;
goto err0;
}
mutex_unlock(&venc.venc_lock);
return size;
}
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
display_output_type_show, display_output_type_store);
/* driver */
static int venc_panel_probe(struct omap_dss_device *dssdev)
{
dssdev->panel.timings = omap_dss_pal_timings;
return device_create_file(&dssdev->dev, &dev_attr_output_type);
}
static void venc_panel_remove(struct omap_dss_device *dssdev)
{
device_remove_file(&dssdev->dev, &dev_attr_output_type);
}
static int venc_panel_enable(struct omap_dss_device *dssdev)
{
int r = 0;
DSSDBG("venc_enable_display\n");
mutex_lock(&venc.venc_lock);
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
goto err0;
}
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
r = -EINVAL;
goto err1;
}
if (dssdev->platform_enable)
dssdev->platform_enable(dssdev);
r = venc_runtime_get();
if (r)
goto err1;
r = venc_power_on(dssdev);
if (r)
goto err2;
goto err1;
venc.wss_data = 0;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&venc.venc_lock);
return 0;
err2:
venc_runtime_put();
err1:
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
omap_dss_stop_device(dssdev);
err0:
mutex_unlock(&venc.venc_lock);
return r;
}
static void venc_panel_disable(struct omap_dss_device *dssdev)
void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
{
DSSDBG("venc_disable_display\n");
DSSDBG("venc_display_disable\n");
mutex_lock(&venc.venc_lock);
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
goto end;
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
/* suspended is the same as disabled with venc */
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
goto end;
}
venc_power_off(dssdev);
venc_runtime_put();
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev);
end:
mutex_unlock(&venc.venc_lock);
}
static int venc_panel_suspend(struct omap_dss_device *dssdev)
{
venc_panel_disable(dssdev);
return 0;
}
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
static int venc_panel_resume(struct omap_dss_device *dssdev)
{
return venc_panel_enable(dssdev);
mutex_unlock(&venc.venc_lock);
}
static void venc_set_timings(struct omap_dss_device *dssdev,
void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
DSSDBG("venc_set_timings\n");
mutex_lock(&venc.venc_lock);
/* Reset WSS data when the TV standard changes. */
if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
if (memcmp(&venc.timings, timings, sizeof(*timings)))
venc.wss_data = 0;
dssdev->panel.timings = *timings;
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_panel_disable(dssdev);
venc_panel_enable(dssdev);
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);
}
static int venc_check_timings(struct omap_dss_device *dssdev,
int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
DSSDBG("venc_check_timings\n");
......@@ -668,13 +595,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
return -EINVAL;
}
static u32 venc_get_wss(struct omap_dss_device *dssdev)
u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
{
/* Invert due to VENC_L21_WC_CTL:INV=1 */
return (venc.wss_data >> 8) ^ 0xfffff;
}
static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
const struct venc_config *config;
int r;
......@@ -683,7 +610,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
mutex_lock(&venc.venc_lock);
config = venc_timings_to_config(&dssdev->panel.timings);
config = venc_timings_to_config(&venc.timings);
/* Invert due to VENC_L21_WC_CTL:INV=1 */
venc.wss_data = (wss ^ 0xfffff) << 8;
......@@ -703,30 +630,25 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
return r;
}
static struct omap_dss_driver venc_driver = {
.probe = venc_panel_probe,
.remove = venc_panel_remove,
void omapdss_venc_set_type(struct omap_dss_device *dssdev,
enum omap_dss_venc_type type)
{
mutex_lock(&venc.venc_lock);
.enable = venc_panel_enable,
.disable = venc_panel_disable,
.suspend = venc_panel_suspend,
.resume = venc_panel_resume,
venc.type = type;
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
mutex_unlock(&venc.venc_lock);
}
.set_timings = venc_set_timings,
.check_timings = venc_check_timings,
void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
bool invert_polarity)
{
mutex_lock(&venc.venc_lock);
.get_wss = venc_get_wss,
.set_wss = venc_set_wss,
venc.invert_polarity = invert_polarity;
.driver = {
.name = "venc",
.owner = THIS_MODULE,
},
};
/* driver end */
mutex_unlock(&venc.venc_lock);
}
static int __init venc_init_display(struct omap_dss_device *dssdev)
{
......@@ -897,9 +819,9 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
venc_runtime_put();
r = omap_dss_register_driver(&venc_driver);
r = venc_panel_init();
if (r)
goto err_reg_panel_driver;
goto err_panel_init;
dss_debugfs_create_file("venc", venc_dump_regs);
......@@ -907,7 +829,7 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
return 0;
err_reg_panel_driver:
err_panel_init:
err_runtime_get:
pm_runtime_disable(&pdev->dev);
venc_put_clocks();
......@@ -923,7 +845,7 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
venc.vdda_dac_reg = NULL;
}
omap_dss_unregister_driver(&venc_driver);
venc_panel_exit();
pm_runtime_disable(&pdev->dev);
venc_put_clocks();
......
/*
* Copyright (C) 2009 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
* VENC panel driver
*
* 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/>.
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <video/omapdss.h>
#include "dss.h"
static struct {
struct mutex lock;
} venc_panel;
static ssize_t display_output_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
const char *ret;
switch (dssdev->phy.venc.type) {
case OMAP_DSS_VENC_TYPE_COMPOSITE:
ret = "composite";
break;
case OMAP_DSS_VENC_TYPE_SVIDEO:
ret = "svideo";
break;
default:
return -EINVAL;
}
return snprintf(buf, PAGE_SIZE, "%s\n", ret);
}
static ssize_t display_output_type_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
enum omap_dss_venc_type new_type;
if (sysfs_streq("composite", buf))
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
else if (sysfs_streq("svideo", buf))
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
else
return -EINVAL;
mutex_lock(&venc_panel.lock);
if (dssdev->phy.venc.type != new_type) {
dssdev->phy.venc.type = new_type;
omapdss_venc_set_type(dssdev, new_type);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
omapdss_venc_display_disable(dssdev);
omapdss_venc_display_enable(dssdev);
}
}
mutex_unlock(&venc_panel.lock);
return size;
}
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
display_output_type_show, display_output_type_store);
static int venc_panel_probe(struct omap_dss_device *dssdev)
{
/* set default timings to PAL */
const struct omap_video_timings default_timings = {
.x_res = 720,
.y_res = 574,
.pixel_clock = 13500,
.hsw = 64,
.hfp = 12,
.hbp = 68,
.vsw = 5,
.vfp = 5,
.vbp = 41,
.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
.interlace = true,
};
mutex_init(&venc_panel.lock);
dssdev->panel.timings = default_timings;
return device_create_file(&dssdev->dev, &dev_attr_output_type);
}
static void venc_panel_remove(struct omap_dss_device *dssdev)
{
device_remove_file(&dssdev->dev, &dev_attr_output_type);
}
static int venc_panel_enable(struct omap_dss_device *dssdev)
{
int r;
dev_dbg(&dssdev->dev, "venc_panel_enable\n");
mutex_lock(&venc_panel.lock);
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
r = -EINVAL;
goto err;
}
omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
omapdss_venc_invert_vid_out_polarity(dssdev,
dssdev->phy.venc.invert_polarity);
r = omapdss_venc_display_enable(dssdev);
if (r)
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&venc_panel.lock);
return 0;
err:
mutex_unlock(&venc_panel.lock);
return r;
}
static void venc_panel_disable(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "venc_panel_disable\n");
mutex_lock(&venc_panel.lock);
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
goto end;
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
/* suspended is the same as disabled with venc */
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
goto end;
}
omapdss_venc_display_disable(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
end:
mutex_unlock(&venc_panel.lock);
}
static int venc_panel_suspend(struct omap_dss_device *dssdev)
{
venc_panel_disable(dssdev);
return 0;
}
static int venc_panel_resume(struct omap_dss_device *dssdev)
{
return venc_panel_enable(dssdev);
}
static void venc_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
mutex_lock(&venc_panel.lock);
omapdss_venc_set_timings(dssdev, timings);
dssdev->panel.timings = *timings;
mutex_unlock(&venc_panel.lock);
}
static int venc_panel_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
return omapdss_venc_check_timings(dssdev, timings);
}
static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
{
dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
return omapdss_venc_get_wss(dssdev);
}
static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
return omapdss_venc_set_wss(dssdev, wss);
}
static struct omap_dss_driver venc_driver = {
.probe = venc_panel_probe,
.remove = venc_panel_remove,
.enable = venc_panel_enable,
.disable = venc_panel_disable,
.suspend = venc_panel_suspend,
.resume = venc_panel_resume,
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
.set_timings = venc_panel_set_timings,
.check_timings = venc_panel_check_timings,
.get_wss = venc_panel_get_wss,
.set_wss = venc_panel_set_wss,
.driver = {
.name = "venc",
.owner = THIS_MODULE,
},
};
int venc_panel_init(void)
{
return omap_dss_register_driver(&venc_driver);
}
void venc_panel_exit(void)
{
omap_dss_unregister_driver(&venc_driver);
}
......@@ -243,7 +243,7 @@ void rfbi_bus_unlock(void);
/* DSI */
struct omap_dss_dsi_videomode_data {
struct omap_dss_dsi_videomode_timings {
/* DSI video mode blanking data */
/* Unit: byte clock cycles */
u16 hsa;
......@@ -564,7 +564,7 @@ struct omap_dss_device {
enum omap_dss_dsi_pixel_format dsi_pix_fmt;
enum omap_dss_dsi_mode dsi_mode;
struct omap_dss_dsi_videomode_data dsi_vm_data;
struct omap_dss_dsi_videomode_timings dsi_vm_timings;
} panel;
struct {
......@@ -719,6 +719,15 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool enable);
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
enum omap_dss_dsi_pixel_format fmt);
void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
enum omap_dss_dsi_mode mode);
void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
struct omap_dss_dsi_videomode_timings *timings);
int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
void (*callback)(int, void *), void *data);
......@@ -734,22 +743,29 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
void dpi_set_timings(struct omap_dss_device *dssdev,
void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int dpi_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines);
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs);
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
u16 *x, u16 *y, u16 *w, u16 *h);
int omap_rfbi_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h,
void (*callback)(void *), void *data);
int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
void *data);
int omap_rfbi_configure(struct omap_dss_device *dssdev);
void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev,
int pixel_size);
void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
int data_lines);
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
struct rfbi_timings *timings);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment