Merge 3.6-rc4 to get latest OMAP and device tree fixes.
{ "dss_core", "omapdss_dss", -1 },
{ "dss_dispc", "omapdss_dispc", -1 },
{ "dss_rfbi", "omapdss_rfbi", -1 },
- { "dss_venc", "omapdss_venc", -1 },
{ "dss_dsi1", "omapdss_dsi", 0 },
{ "dss_dsi2", "omapdss_dsi", 1 },
{ "dss_hdmi", "omapdss_hdmi", -1 },
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__);
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,
struct omap_dss_device *dssdev;
struct panel_config *panel_config;
+
+ struct mutex lock;
};
static inline struct panel_generic_dpi_data
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;
drv_data->dssdev = dssdev;
drv_data->panel_config = panel_config;
+ mutex_init(&drv_data->lock);
+
dev_set_drvdata(&dssdev->dev, drv_data);
return 0;
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 = {
.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 = {
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;
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,
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;
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);
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;
* 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");
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;
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");
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);
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);
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;
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);
}
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;
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,
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 \
}
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);
}
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
- struct omap_video_timings *timings)
+ const struct omap_video_timings *timings)
{
unsigned long flags;
unsigned irqs[32];
};
+struct dispc_features {
+ u8 sw_start;
+ u8 fp_start;
+ u8 bp_start;
+ u16 sw_max;
+ u16 vp_max;
+ u16 hp_max;
+ int (*calc_scaling) (enum omap_channel channel,
+ const struct omap_video_timings *mgr_timings,
+ u16 width, u16 height, u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode, bool *five_taps,
+ int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+ 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);
+};
+
static struct {
struct platform_device *pdev;
void __iomem *base;
bool ctx_valid;
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
+ const struct dispc_features *feat;
+
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
spinlock_t irq_stats_lock;
struct dispc_irq_stats irq_stats;
return core_clk;
}
-static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
+static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width,
+ u16 height, u16 out_width, u16 out_height)
+{
+ unsigned long pclk = dispc_mgr_pclk_rate(channel);
+
+ if (height > out_height && width > out_width)
+ return pclk * 4;
+ else
+ return pclk * 2;
+}
+
+static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width,
u16 height, u16 out_width, u16 out_height)
{
unsigned int hf, vf;
hf = 2;
else
hf = 1;
-
if (height > out_height)
vf = 2;
else
vf = 1;
- if (cpu_is_omap24xx()) {
- if (vf > 1 && hf > 1)
- return pclk * 4;
- else
- return pclk * 2;
- } else if (cpu_is_omap34xx()) {
- return pclk * vf * hf;
- } else {
- if (hf > 1)
- return DIV_ROUND_UP(pclk, out_width) * width;
- else
- return pclk;
+ return pclk * vf * hf;
+}
+
+static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width,
+ u16 height, u16 out_width, u16 out_height)
+{
+ unsigned long pclk = dispc_mgr_pclk_rate(channel);
+
+ if (width > out_width)
+ return DIV_ROUND_UP(pclk, out_width) * width;
+ else
+ return pclk;
+}
+
+static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
+ const struct omap_video_timings *mgr_timings,
+ u16 width, u16 height, u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode, bool *five_taps,
+ int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+ u16 pos_x, unsigned long *core_clk)
+{
+ int error;
+ u16 in_width, in_height;
+ int min_factor = min(*decim_x, *decim_y);
+ const int maxsinglelinewidth =
+ dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+ *five_taps = false;
+
+ do {
+ in_height = DIV_ROUND_UP(height, *decim_y);
+ in_width = DIV_ROUND_UP(width, *decim_x);
+ *core_clk = dispc.feat->calc_core_clk(channel, in_width,
+ in_height, out_width, out_height);
+ error = (in_width > maxsinglelinewidth || !*core_clk ||
+ *core_clk > dispc_core_clk_rate());
+ if (error) {
+ if (*decim_x == *decim_y) {
+ *decim_x = min_factor;
+ ++*decim_y;
+ } else {
+ swap(*decim_x, *decim_y);
+ if (*decim_x < *decim_y)
+ ++*decim_x;
+ }
+ }
+ } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+ if (in_width > maxsinglelinewidth) {
+ DSSERR("Cannot scale max input width exceeded");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
+ const struct omap_video_timings *mgr_timings,
+ u16 width, u16 height, u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode, bool *five_taps,
+ int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+ u16 pos_x, unsigned long *core_clk)
+{
+ int error;
+ u16 in_width, in_height;
+ int min_factor = min(*decim_x, *decim_y);
+ const int maxsinglelinewidth =
+ dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+ do {
+ in_height = DIV_ROUND_UP(height, *decim_y);
+ in_width = DIV_ROUND_UP(width, *decim_x);
+ *core_clk = calc_core_clk_five_taps(channel, mgr_timings,
+ in_width, in_height, out_width, out_height, color_mode);
+
+ error = check_horiz_timing_omap3(channel, mgr_timings, pos_x,
+ in_width, in_height, out_width, out_height);
+
+ if (in_width > maxsinglelinewidth)
+ if (in_height > out_height &&
+ in_height < out_height * 2)
+ *five_taps = false;
+ if (!*five_taps)
+ *core_clk = dispc.feat->calc_core_clk(channel, in_width,
+ in_height, out_width, out_height);
+
+ error = (error || in_width > maxsinglelinewidth * 2 ||
+ (in_width > maxsinglelinewidth && *five_taps) ||
+ !*core_clk || *core_clk > dispc_core_clk_rate());
+ if (error) {
+ if (*decim_x == *decim_y) {
+ *decim_x = min_factor;
+ ++*decim_y;
+ } else {
+ swap(*decim_x, *decim_y);
+ if (*decim_x < *decim_y)
+ ++*decim_x;
+ }
+ }
+ } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
+
+ if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height,
+ out_width, out_height)){
+ DSSERR("horizontal timing too tight\n");
+ return -EINVAL;
+ }
+
+ if (in_width > (maxsinglelinewidth * 2)) {
+ DSSERR("Cannot setup scaling");
+ DSSERR("width exceeds maximum width possible");
+ return -EINVAL;
+ }
+
+ if (in_width > maxsinglelinewidth && *five_taps) {
+ DSSERR("cannot setup scaling with five taps");
+ return -EINVAL;
}
+ return 0;
+}
+
+static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
+ const struct omap_video_timings *mgr_timings,
+ u16 width, u16 height, u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode, bool *five_taps,
+ int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
+ u16 pos_x, unsigned long *core_clk)
+{
+ u16 in_width, in_width_max;
+ int decim_x_min = *decim_x;
+ u16 in_height = DIV_ROUND_UP(height, *decim_y);
+ const int maxsinglelinewidth =
+ dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
+
+ in_width_max = dispc_core_clk_rate() /
+ DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width);
+ *decim_x = DIV_ROUND_UP(width, in_width_max);
+
+ *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
+ if (*decim_x > *x_predecim)
+ return -EINVAL;
+
+ do {
+ in_width = DIV_ROUND_UP(width, *decim_x);
+ } while (*decim_x <= *x_predecim &&
+ in_width > maxsinglelinewidth && ++*decim_x);
+
+ if (in_width > maxsinglelinewidth) {
+ DSSERR("Cannot scale width exceeds max line width");
+ return -EINVAL;
+ }
+
+ *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height,
+ out_width, out_height);
+ return 0;
}
static int dispc_ovl_calc_scaling(enum omap_plane plane,
{
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
- const int maxsinglelinewidth =
- dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
const int max_decim_limit = 16;
unsigned long core_clk = 0;
- int decim_x, decim_y, error, min_factor;
- u16 in_width, in_height, in_width_max = 0;
+ int decim_x, decim_y, ret;
if (width == out_width && height == out_height)
return 0;
decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
- min_factor = min(decim_x, decim_y);
-
if (decim_x > *x_predecim || out_width > width * 8)
return -EINVAL;
if (decim_y > *y_predecim || out_height > height * 8)
return -EINVAL;
- if (cpu_is_omap24xx()) {
- *five_taps = false;
-
- do {
- in_height = DIV_ROUND_UP(height, decim_y);
- in_width = DIV_ROUND_UP(width, decim_x);
- core_clk = calc_core_clk(channel, in_width, in_height,
- out_width, out_height);
- error = (in_width > maxsinglelinewidth || !core_clk ||
- core_clk > dispc_core_clk_rate());
- if (error) {
- if (decim_x == decim_y) {
- decim_x = min_factor;
- decim_y++;
- } else {
- swap(decim_x, decim_y);
- if (decim_x < decim_y)
- decim_x++;
- }
- }
- } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
- error);
-
- if (in_width > maxsinglelinewidth) {
- DSSERR("Cannot scale max input width exceeded");
- return -EINVAL;
- }
- } else if (cpu_is_omap34xx()) {
-
- do {
- in_height = DIV_ROUND_UP(height, decim_y);
- in_width = DIV_ROUND_UP(width, decim_x);
- core_clk = calc_core_clk_five_taps(channel, mgr_timings,
- in_width, in_height, out_width, out_height,
- color_mode);
-
- error = check_horiz_timing_omap3(channel, mgr_timings,
- pos_x, in_width, in_height, out_width,
- out_height);
-
- if (in_width > maxsinglelinewidth)
- if (in_height > out_height &&
- in_height < out_height * 2)
- *five_taps = false;
- if (!*five_taps)
- core_clk = calc_core_clk(channel, in_width,
- in_height, out_width, out_height);
- error = (error || in_width > maxsinglelinewidth * 2 ||
- (in_width > maxsinglelinewidth && *five_taps) ||
- !core_clk || core_clk > dispc_core_clk_rate());
- if (error) {
- if (decim_x == decim_y) {
- decim_x = min_factor;
- decim_y++;
- } else {
- swap(decim_x, decim_y);
- if (decim_x < decim_y)
- decim_x++;
- }
- }
- } while (decim_x <= *x_predecim && decim_y <= *y_predecim
- && error);
-
- if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
- height, out_width, out_height)){
- DSSERR("horizontal timing too tight\n");
- return -EINVAL;
- }
-
- if (in_width > (maxsinglelinewidth * 2)) {
- DSSERR("Cannot setup scaling");
- DSSERR("width exceeds maximum width possible");
- return -EINVAL;
- }
-
- if (in_width > maxsinglelinewidth && *five_taps) {
- DSSERR("cannot setup scaling with five taps");
- return -EINVAL;
- }
- } else {
- int decim_x_min = decim_x;
- in_height = DIV_ROUND_UP(height, decim_y);
- in_width_max = dispc_core_clk_rate() /
- DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
- out_width);
- decim_x = DIV_ROUND_UP(width, in_width_max);
-
- decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
- if (decim_x > *x_predecim)
- return -EINVAL;
-
- do {
- in_width = DIV_ROUND_UP(width, decim_x);
- } while (decim_x <= *x_predecim &&
- in_width > maxsinglelinewidth && decim_x++);
-
- if (in_width > maxsinglelinewidth) {
- DSSERR("Cannot scale width exceeds max line width");
- return -EINVAL;
- }
-
- core_clk = calc_core_clk(channel, in_width, in_height,
- out_width, out_height);
- }
+ ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height,
+ out_width, out_height, color_mode, five_taps, x_predecim,
+ y_predecim, &decim_x, &decim_y, pos_x, &core_clk);
+ if (ret)
+ return ret;
DSSDBG("required core clk rate = %lu Hz\n", core_clk);
DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
int vsw, int vfp, int vbp)
{
- if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
- if (hsw < 1 || hsw > 64 ||
- hfp < 1 || hfp > 256 ||
- hbp < 1 || hbp > 256 ||
- vsw < 1 || vsw > 64 ||
- vfp < 0 || vfp > 255 ||
- vbp < 0 || vbp > 255)
- return false;
- } else {
- if (hsw < 1 || hsw > 256 ||
- hfp < 1 || hfp > 4096 ||
- hbp < 1 || hbp > 4096 ||
- vsw < 1 || vsw > 256 ||
- vfp < 0 || vfp > 4095 ||
- vbp < 0 || vbp > 4095)
- return false;
- }
-
+ if (hsw < 1 || hsw > dispc.feat->sw_max ||
+ hfp < 1 || hfp > dispc.feat->hp_max ||
+ hbp < 1 || hbp > dispc.feat->hp_max ||
+ vsw < 1 || vsw > dispc.feat->sw_max ||
+ vfp < 0 || vfp > dispc.feat->vp_max ||
+ vbp < 0 || vbp > dispc.feat->vp_max)
+ return false;
return true;
}
u32 timing_h, timing_v, l;
bool onoff, rf, ipc;
- if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
- timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
- FLD_VAL(hbp-1, 27, 20);
-
- timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
- FLD_VAL(vbp, 27, 20);
- } else {
- timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
- FLD_VAL(hbp-1, 31, 20);
-
- timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
- FLD_VAL(vbp, 31, 20);
- }
+ timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
+ FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
+ FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
+ timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
+ FLD_VAL(vfp, dispc.feat->fp_start, 8) |
+ FLD_VAL(vbp, dispc.feat->bp_start, 20);
dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
ovl->name);
dispc_ovl_enable(ovl->id, false);
dispc_mgr_go(ovl->manager->id);
- mdelay(50);
+ msleep(50);
}
}
}
dispc_mgr_go(mgr->id);
- mdelay(50);
+ msleep(50);
if (enable)
dssdev->driver->enable(dssdev);
dispc_ovl_enable_zorder_planes();
}
+static const struct dispc_features omap24xx_dispc_feats __initconst = {
+ .sw_start = 5,
+ .fp_start = 15,
+ .bp_start = 27,
+ .sw_max = 64,
+ .vp_max = 255,
+ .hp_max = 256,
+ .calc_scaling = dispc_ovl_calc_scaling_24xx,
+ .calc_core_clk = calc_core_clk_24xx,
+};
+
+static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
+ .sw_start = 5,
+ .fp_start = 15,
+ .bp_start = 27,
+ .sw_max = 64,
+ .vp_max = 255,
+ .hp_max = 256,
+ .calc_scaling = dispc_ovl_calc_scaling_34xx,
+ .calc_core_clk = calc_core_clk_34xx,
+};
+
+static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
+ .sw_start = 7,
+ .fp_start = 19,
+ .bp_start = 31,
+ .sw_max = 256,
+ .vp_max = 4095,
+ .hp_max = 4096,
+ .calc_scaling = dispc_ovl_calc_scaling_34xx,
+ .calc_core_clk = calc_core_clk_34xx,
+};
+
+static const struct dispc_features omap44xx_dispc_feats __initconst = {
+ .sw_start = 7,
+ .fp_start = 19,
+ .bp_start = 31,
+ .sw_max = 256,
+ .vp_max = 4095,
+ .hp_max = 4096,
+ .calc_scaling = dispc_ovl_calc_scaling_44xx,
+ .calc_core_clk = calc_core_clk_44xx,
+};
+
+static int __init dispc_init_features(struct device *dev)
+{
+ const struct dispc_features *src;
+ struct dispc_features *dst;
+
+ dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ if (!dst) {
+ dev_err(dev, "Failed to allocate DISPC Features\n");
+ return -ENOMEM;
+ }
+
+ if (cpu_is_omap24xx()) {
+ src = &omap24xx_dispc_feats;
+ } else if (cpu_is_omap34xx()) {
+ if (omap_rev() < OMAP3430_REV_ES3_0)
+ src = &omap34xx_rev1_0_dispc_feats;
+ else
+ src = &omap34xx_rev3_0_dispc_feats;
+ } else if (cpu_is_omap44xx()) {
+ src = &omap44xx_dispc_feats;
+ } else {
+ return -ENODEV;
+ }
+
+ memcpy(dst, src, sizeof(*dst));
+ dispc.feat = dst;
+
+ return 0;
+}
+
/* DISPC HW IP initialisation */
static int __init omap_dispchw_probe(struct platform_device *pdev)
{
dispc.pdev = pdev;
+ r = dispc_init_features(&dispc.pdev->dev);
+ if (r)
+ return r;
+
spin_lock_init(&dispc.irq_lock);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
#include <plat/cpu.h>
#include "dss.h"
+#include "dss_features.h"
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)
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;
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;
{
int r;
- if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
+ mutex_lock(&dpi.lock);
+
+ if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !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);
goto err_start_dev;
}
- if (cpu_is_omap34xx()) {
+ if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
r = regulator_enable(dpi.vdds_dsi_reg);
if (r)
goto err_reg_enable;
if (r)
goto err_mgr_enable;
+ mutex_unlock(&dpi.lock);
+
return 0;
err_mgr_enable:
err_get_dsi:
dispc_runtime_put();
err_get_dispc:
- if (cpu_is_omap34xx())
+ if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
regulator_disable(dpi.vdds_dsi_reg);
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)) {
dispc_runtime_put();
- if (cpu_is_omap34xx())
+ if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
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,
- struct omap_video_timings *timings)
+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)
} 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)
}
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");
- if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
+ if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
+ dpi.vdds_dsi_reg == NULL) {
struct regulator *vdds_dsi;
vdds_dsi = dss_get_vdds_dsi();
static int __init omap_dpi_probe(struct platform_device *pdev)
{
+ mutex_init(&dpi.lock);
+
dpi_probe_pdata(pdev);
return 0;
unsigned scp_clk_refcount;
struct dss_lcd_mgr_config mgr_config;
+ struct omap_video_timings timings;
+ enum omap_dss_dsi_pixel_format pix_fmt;
+ enum omap_dss_dsi_mode mode;
+ struct omap_dss_dsi_videomode_timings vm_timings;
};
struct dsi_packet_sent_handler_data {
dsi_cio_timings(dsidev);
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
/* DDR_CLK_ALWAYS_ON */
REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
- dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13);
+ dsi->vm_timings.ddr_clk_always_on, 13, 13);
}
dsi->ulps_enabled = false;
bool enable)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
dsi_force_tx_stop_mode_io(dsidev);
/* start the DDR clock by sending a NULL packet */
- if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable)
+ if (dsi->vm_timings.ddr_clk_always_on && enable)
dsi_vc_send_null(dssdev, channel);
}
EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
int num_line_buffers;
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
- int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ int bpp = dsi_get_pixel_size(dsi->pix_fmt);
unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
- struct omap_video_timings *timings = &dssdev->panel.timings;
+ struct omap_video_timings *timings = &dsi->timings;
/*
* Don't use line buffers if width is greater than the video
* port's line buffer size
static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end;
- bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ bool vsync_end = dsi->vm_timings.vp_vsync_end;
+ bool hsync_end = dsi->vm_timings.vp_hsync_end;
u32 r;
r = dsi_read_reg(dsidev, DSI_CTRL);
static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode;
- int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode;
- int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode;
- int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode;
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ int blanking_mode = dsi->vm_timings.blanking_mode;
+ int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
+ int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
+ int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
u32 r;
/*
int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
int tclk_trail, ths_exit, exiths_clk;
bool ddr_alwon;
- struct omap_video_timings *timings = &dssdev->panel.timings;
- int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ struct omap_video_timings *timings = &dsi->timings;
+ int bpp = dsi_get_pixel_size(dsi->pix_fmt);
int ndl = dsi->num_lanes_used - 1;
int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
static int dsi_proto_config(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
u32 r;
int buswidth = 0;
dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
- switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {
+ switch (dsi_get_pixel_size(dsi->pix_fmt)) {
case 16:
buswidth = 0;
break;
dsi_config_vp_num_line_buffers(dssdev);
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
dsi_config_vp_sync_events(dssdev);
dsi_config_blanking_modes(dssdev);
dsi_config_cmd_mode_interleaving(dssdev);
DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
enter_hs_mode_lat, exit_hs_mode_lat);
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
/* TODO: Implement a video mode check_timings function */
- int hsa = dssdev->panel.dsi_vm_data.hsa;
- int hfp = dssdev->panel.dsi_vm_data.hfp;
- int hbp = dssdev->panel.dsi_vm_data.hbp;
- int vsa = dssdev->panel.dsi_vm_data.vsa;
- int vfp = dssdev->panel.dsi_vm_data.vfp;
- int vbp = dssdev->panel.dsi_vm_data.vbp;
- int window_sync = dssdev->panel.dsi_vm_data.window_sync;
- bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
- struct omap_video_timings *timings = &dssdev->panel.timings;
- int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ int hsa = dsi->vm_timings.hsa;
+ int hfp = dsi->vm_timings.hfp;
+ int hbp = dsi->vm_timings.hbp;
+ int vsa = dsi->vm_timings.vsa;
+ int vfp = dsi->vm_timings.vfp;
+ int vbp = dsi->vm_timings.vbp;
+ int window_sync = dsi->vm_timings.window_sync;
+ bool hsync_end = dsi->vm_timings.vp_hsync_end;
+ struct omap_video_timings *timings = &dsi->timings;
+ int bpp = dsi_get_pixel_size(dsi->pix_fmt);
int tl, t_he, width_bytes;
t_he = hsync_end ?
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ int bpp = dsi_get_pixel_size(dsi->pix_fmt);
u8 data_type;
u16 word_count;
int r;
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
- switch (dssdev->panel.dsi_pix_fmt) {
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ switch (dsi->pix_fmt) {
case OMAP_DSS_DSI_FMT_RGB888:
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
break;
/* MODE, 1 = video mode */
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
- word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
+ word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
dsi_vc_write_long_header(dsidev, channel, data_type,
word_count, 0);
r = dss_mgr_enable(dssdev->manager);
if (r) {
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
dsi_if_enable(dsidev, false);
dsi_vc_enable(dsidev, channel, false);
}
void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
dsi_if_enable(dsidev, false);
dsi_vc_enable(dsidev, channel, false);
}
EXPORT_SYMBOL(dsi_disable_video_output);
-static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
- u16 w, u16 h)
+static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
int r;
const unsigned channel = dsi->update_channel;
const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+ u16 w = dsi->timings.x_res;
+ u16 h = dsi->timings.y_res;
DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
- bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+ bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
bytespl = w * bytespp;
bytespf = bytespl * h;
msecs_to_jiffies(250));
BUG_ON(r == 0);
+ dss_mgr_set_timings(dssdev->manager, &dsi->timings);
+
dss_mgr_start_update(dssdev->manager);
if (dsi->te_enabled) {
dsi->framedone_callback = callback;
dsi->framedone_data = data;
- dssdev->driver->get_resolution(dssdev, &dw, &dh);
+ dw = dsi->timings.x_res;
+ dh = dsi->timings.y_res;
#ifdef DEBUG
dsi->update_bytes = dw * dh *
- dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+ dsi_get_pixel_size(dsi->pix_fmt) / 8;
#endif
- dsi_update_screen_dispc(dssdev, dw, dh);
+ dsi_update_screen_dispc(dssdev);
return 0;
}
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct omap_video_timings timings;
int r;
u32 irq = 0;
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
- u16 dw, dh;
-
- dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
- timings.x_res = dw;
- timings.y_res = dh;
- timings.hsw = 1;
- timings.hfp = 1;
- timings.hbp = 1;
- timings.vsw = 1;
- timings.vfp = 0;
- timings.vbp = 0;
+ if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
+ dsi->timings.hsw = 1;
+ dsi->timings.hfp = 1;
+ dsi->timings.hbp = 1;
+ dsi->timings.vsw = 1;
+ dsi->timings.vfp = 0;
+ dsi->timings.vbp = 0;
irq = dispc_mgr_get_framedone_irq(dssdev->manager->id);
dsi->mgr_config.stallmode = true;
dsi->mgr_config.fifohandcheck = true;
} else {
- timings = dssdev->panel.timings;
-
dsi->mgr_config.stallmode = false;
dsi->mgr_config.fifohandcheck = false;
}
* override interlace, logic level and edge related parameters in
* omap_video_timings with default values
*/
- timings.interlace = false;
- timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
- timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+ dsi->timings.interlace = false;
+ dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+ dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+ dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+ dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+ dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
- dss_mgr_set_timings(dssdev->manager, &timings);
+ dss_mgr_set_timings(dssdev->manager, &dsi->timings);
r = dsi_configure_dispc_clocks(dssdev);
if (r)
dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
dsi->mgr_config.video_port_width =
- dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+ dsi_get_pixel_size(dsi->pix_fmt);
dsi->mgr_config.lcden_sig_polarity = 0;
dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config);
return 0;
err1:
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE)
+ if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
omap_dispc_unregister_isr(dsi_framedone_irq_callback,
(void *) dssdev, irq);
err:
static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
{
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+ if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
u32 irq;
irq = dispc_mgr_get_framedone_irq(dssdev->manager->id);
}
EXPORT_SYMBOL(omapdss_dsi_enable_te);
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+ mutex_lock(&dsi->lock);
+
+ dsi->timings = *timings;
+
+ mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_timings);
+
+void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+ mutex_lock(&dsi->lock);
+
+ dsi->timings.x_res = w;
+ dsi->timings.y_res = h;
+
+ mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_size);
+
+void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
+ enum omap_dss_dsi_pixel_format fmt)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+ mutex_lock(&dsi->lock);
+
+ dsi->pix_fmt = fmt;
+
+ mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
+
+void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_dsi_mode mode)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+ mutex_lock(&dsi->lock);
+
+ dsi->mode = mode;
+
+ mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
+
+void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
+ struct omap_dss_dsi_videomode_timings *timings)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+ mutex_lock(&dsi->lock);
+
+ dsi->vm_timings = *timings;
+
+ mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
+
static int __init dsi_init_display(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
DSSDBG("DSI init\n");
- if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+ if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
}
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/gfp.h>
#include <video/omapdss.h>
static int dss_runtime_get(void);
static void dss_runtime_put(void);
+struct dss_features {
+ u8 fck_div_max;
+ u8 dss_fck_multiplier;
+ const char *clk_name;
+};
+
static struct {
struct platform_device *pdev;
void __iomem *base;
bool ctx_valid;
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
+
+ const struct dss_features *feat;
} dss;
static const char * const dss_generic_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
};
+static const struct dss_features omap24xx_dss_feats __initconst = {
+ .fck_div_max = 16,
+ .dss_fck_multiplier = 2,
+ .clk_name = NULL,
+};
+
+static const struct dss_features omap34xx_dss_feats __initconst = {
+ .fck_div_max = 16,
+ .dss_fck_multiplier = 2,
+ .clk_name = "dpll4_m4_ck",
+};
+
+static const struct dss_features omap3630_dss_feats __initconst = {
+ .fck_div_max = 32,
+ .dss_fck_multiplier = 1,
+ .clk_name = "dpll4_m4_ck",
+};
+
+static const struct dss_features omap44xx_dss_feats __initconst = {
+ .fck_div_max = 32,
+ .dss_fck_multiplier = 1,
+ .clk_name = "dpll_per_m5x2_ck",
+};
+
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
{
__raw_writel(val, dss.base + idx.idx);
#undef SR
#undef RR
-void dss_sdi_init(u8 datapairs)
+void dss_sdi_init(int datapairs)
{
u32 l;
return dss_generic_clk_source_names[clk_src];
}
-
void dss_dump_clocks(struct seq_file *s)
{
unsigned long dpll4_ck_rate;
seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
- if (cpu_is_omap3630() || cpu_is_omap44xx())
- seq_printf(s, "%s (%s) = %lu / %lu = %lu\n",
- fclk_name, fclk_real_name,
- dpll4_ck_rate,
- dpll4_ck_rate / dpll4_m4_ck_rate,
- fclk_rate);
- else
- seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
- fclk_name, fclk_real_name,
- dpll4_ck_rate,
- dpll4_ck_rate / dpll4_m4_ck_rate,
- fclk_rate);
+ seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n",
+ fclk_name, fclk_real_name, dpll4_ck_rate,
+ dpll4_ck_rate / dpll4_m4_ck_rate,
+ dss.feat->dss_fck_multiplier, fclk_rate);
} else {
seq_printf(s, "%s (%s) = %lu\n",
fclk_name, fclk_real_name,
}
}
-/* calculate clock rates using dividers in cinfo */
-int dss_calc_clock_rates(struct dss_clock_info *cinfo)
-{
- if (dss.dpll4_m4_ck) {
- unsigned long prate;
- u16 fck_div_max = 16;
-
- if (cpu_is_omap3630() || cpu_is_omap44xx())
- fck_div_max = 32;
-
- if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
- return -EINVAL;
-
- prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
- cinfo->fck = prate / cinfo->fck_div;
- } else {
- if (cinfo->fck_div != 0)
- return -EINVAL;
- cinfo->fck = clk_get_rate(dss.dss_clk);
- }
-
- return 0;
-}
-
int dss_set_clock_div(struct dss_clock_info *cinfo)
{
if (dss.dpll4_m4_ck) {
return 0;
}
-int dss_get_clock_div(struct dss_clock_info *cinfo)
-{
- cinfo->fck = clk_get_rate(dss.dss_clk);
-
- if (dss.dpll4_m4_ck) {
- unsigned long prate;
-
- prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
- if (cpu_is_omap3630() || cpu_is_omap44xx())
- cinfo->fck_div = prate / (cinfo->fck);
- else
- cinfo->fck_div = prate / (cinfo->fck / 2);
- } else {
- cinfo->fck_div = 0;
- }
-
- return 0;
-}
-
unsigned long dss_get_dpll4_rate(void)
{
if (dss.dpll4_m4_ck)
unsigned long fck, max_dss_fck;
- u16 fck_div, fck_div_max = 16;
+ u16 fck_div;
int match = 0;
int min_fck_per_pck;
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
fck = clk_get_rate(dss.dss_clk);
- if (req_pck == dss.cache_req_pck &&
- ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
- dss.cache_dss_cinfo.fck == fck)) {
+ if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
+ dss.cache_dss_cinfo.fck == fck) {
DSSDBG("dispc clock info found from cache.\n");
*dss_cinfo = dss.cache_dss_cinfo;
*dispc_cinfo = dss.cache_dispc_cinfo;
goto found;
} else {
- if (cpu_is_omap3630() || cpu_is_omap44xx())
- fck_div_max = 32;
-
- for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
+ for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
struct dispc_clock_info cur_dispc;
- if (fck_div_max == 32)
- fck = prate / fck_div;
- else
- fck = prate / fck_div * 2;
+ fck = prate / fck_div * dss.feat->dss_fck_multiplier;
if (fck > max_dss_fck)
continue;
REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
}
-void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
+void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
{
- REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
+ enum omap_display_type dp;
+ dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+
+ /* Complain about invalid selections */
+ WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
+ WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
+
+ /* Select only if we have options */
+ if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
+ REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
}
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
return DSS_VENC_TV_CLK;
+ if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
+ return DSS_HDMI_M_PCLK;
+
return REG_GET(DSS_CONTROL, 15, 15);
}
dss.dss_clk = clk;
- if (cpu_is_omap34xx()) {
- clk = clk_get(NULL, "dpll4_m4_ck");
- if (IS_ERR(clk)) {
- DSSERR("Failed to get dpll4_m4_ck\n");
- r = PTR_ERR(clk);
- goto err;
- }
- } else if (cpu_is_omap44xx()) {
- clk = clk_get(NULL, "dpll_per_m5x2_ck");
- if (IS_ERR(clk)) {
- DSSERR("Failed to get dpll_per_m5x2_ck\n");
- r = PTR_ERR(clk);
- goto err;
- }
- } else { /* omap24xx */
- clk = NULL;
+ clk = clk_get(NULL, dss.feat->clk_name);
+ if (IS_ERR(clk)) {
+ DSSERR("Failed to get %s\n", dss.feat->clk_name);
+ r = PTR_ERR(clk);
+ goto err;
}
dss.dpll4_m4_ck = clk;
}
#endif
+static int __init dss_init_features(struct device *dev)
+{
+ const struct dss_features *src;
+ struct dss_features *dst;
+
+ dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ if (!dst) {
+ dev_err(dev, "Failed to allocate local DSS Features\n");
+ return -ENOMEM;
+ }
+
+ if (cpu_is_omap24xx())
+ src = &omap24xx_dss_feats;
+ else if (cpu_is_omap34xx())
+ src = &omap34xx_dss_feats;
+ else if (cpu_is_omap3630())
+ src = &omap3630_dss_feats;
+ else if (cpu_is_omap44xx())
+ src = &omap44xx_dss_feats;
+ else
+ return -ENODEV;
+
+ memcpy(dst, src, sizeof(*dst));
+ dss.feat = dst;
+
+ return 0;
+}
+
/* DSS HW IP initialisation */
static int __init omap_dsshw_probe(struct platform_device *pdev)
{
dss.pdev = pdev;
+ r = dss_init_features(&dss.pdev->dev);
+ if (r)
+ return r;
+
dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
if (!dss_mem) {
DSSERR("can't get IORESOURCE_MEM DSS\n");
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);
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);
void dss_set_dac_pwrdn_bgz(bool enable);
unsigned long dss_get_dpll4_rate(void);
-int dss_calc_clock_rates(struct dss_clock_info *cinfo);
int dss_set_clock_div(struct dss_clock_info *cinfo);
-int dss_get_clock_div(struct dss_clock_info *cinfo);
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
struct dispc_clock_info *dispc_cinfo);
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
#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);
FEAT_ALPHA_FIXED_ZORDER,
FEAT_FIFO_MERGE,
FEAT_OMAP3_DSI_FIFO_BUG,
+ FEAT_DPI_USES_VDDS_DSI,
};
static const enum dss_feat_id omap3630_dss_feat_list[] = {
FEAT_DSI_VC_OCP_WIDTH,
FEAT_DSI_REVERSE_TXCLKESC,
FEAT_DSI_GNQ,
+ FEAT_DPI_USES_VDDS_DSI,
FEAT_HDMI_CTS_SWMODE,
FEAT_HDMI_AUDIO_USE_MCLK,
FEAT_HANDLE_UV_SEPARATE,
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;
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);
r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
if (r) {
DSSDBG("Failed to start PHY\n");
- goto err;
+ goto err_phy_enable;
}
hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
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)
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
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:
hdmi_runtime_put();
}
-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;
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)
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();
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);
+
+ omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
+
return 0;
}
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");
*/
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);
}
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)
}
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)
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)
{
/* 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)
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:
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)
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;
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)
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;
}
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");
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)
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;
}
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)
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;
- }
+ int r;
- 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;
+ 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,
- struct omap_video_timings *timings)
+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,
- struct omap_video_timings *timings)
+int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
+ struct omap_video_timings *timings)
{
DSSDBG("venc_check_timings\n");
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;
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;
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)
{
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
- if (cpu_is_omap44xx()) {
- seq_printf(s, "VENC currently disabled on OMAP44xx\n");
- return;
- }
-
if (venc_runtime_get())
return;
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);
return 0;
-err_reg_panel_driver:
+err_panel_init:
err_runtime_get:
pm_runtime_disable(&pdev->dev);
venc_put_clocks();
venc.vdda_dac_reg = NULL;
}
- omap_dss_unregister_driver(&venc_driver);
+ venc_panel_exit();
pm_runtime_disable(&pdev->dev);
venc_put_clocks();
int __init venc_init_platform_driver(void)
{
- if (cpu_is_omap44xx())
- return 0;
-
return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
}
void __exit venc_uninit_platform_driver(void)
{
- if (cpu_is_omap44xx())
- return;
-
platform_driver_unregister(&omap_venchw_driver);
}
--- /dev/null
+/*
+ * 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);
+}
break;
if (regno < 16) {
- u16 pal;
+ u32 pal;
pal = ((red >> (16 - var->red.length)) <<
var->red.offset) |
((green >> (16 - var->green.length)) <<
#define DISPC_IRQ_FRAMEDONEWB (1 << 23)
#define DISPC_IRQ_FRAMEDONETV (1 << 24)
#define DISPC_IRQ_WBBUFFEROVERFLOW (1 << 25)
-#define DISPC_IRQ_FRAMEDONE3 (1 << 26)
-#define DISPC_IRQ_VSYNC3 (1 << 27)
-#define DISPC_IRQ_ACBIAS_COUNT_STAT3 (1 << 28)
-#define DISPC_IRQ_SYNC_LOST3 (1 << 29)
+#define DISPC_IRQ_SYNC_LOST3 (1 << 27)
+#define DISPC_IRQ_VSYNC3 (1 << 28)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT3 (1 << 29)
+#define DISPC_IRQ_FRAMEDONE3 (1 << 30)
struct omap_dss_device;
struct omap_overlay_manager;
/* DSI */
-struct omap_dss_dsi_videomode_data {
+struct omap_dss_dsi_videomode_timings {
/* DSI video mode blanking data */
/* Unit: byte clock cycles */
u16 hsa;
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 {
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);
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,
- struct omap_video_timings *timings);
+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