From 24305db864cd62bf4279f745528c3238cbaf1c12 Mon Sep 17 00:00:00 2001 From: Mayuresh Janorkar Date: Tue, 17 May 2011 17:49:40 +0530 Subject: OMAP: DSS2: Add picodlp panel driver PicoDLP is a micro projector from TI. DLP used in OMAP4 is dpp2600 (DLP Pico Projector) The DLP requires commands to be sent over i2c for configurations. To know more about dpp2600 commands please visit: https://focus.ti.com/myti/docs/extranet.tsp?sectionId=403 The picodlp module consists of a dss driver and an i2c_client. To know more please visit: http://www.omappedia.org/wiki/PicoDLP_projector_guide Based on original design from Mythri P K Signed-off-by: Mayuresh Janorkar Signed-off-by: Mythri P K [tomi.valkeinen@ti.com: squashed commits] Signed-off-by: Tomi Valkeinen --- include/video/omap-panel-picodlp.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 include/video/omap-panel-picodlp.h (limited to 'include/video') diff --git a/include/video/omap-panel-picodlp.h b/include/video/omap-panel-picodlp.h new file mode 100644 index 000000000000..1c342ef6f3a1 --- /dev/null +++ b/include/video/omap-panel-picodlp.h @@ -0,0 +1,23 @@ +/* + * panel data for picodlp panel + * + * Copyright (C) 2011 Texas Instruments + * + * Author: Mayuresh Janorkar + * + * 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. + */ +#ifndef __PANEL_PICODLP_H +#define __PANEL_PICODLP_H +/** + * struct : picodlp panel data + * picodlp_adapter_id: i2c_adapter number for picodlp + */ +struct picodlp_panel_data { + int picodlp_adapter_id; + int emu_done_gpio; + int pwrgood_gpio; +}; +#endif /* __PANEL_PICODLP_H */ -- cgit 1.4.1 From 5bc416cba15f43c799fc02727c6d6887f3e35a4e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 15 Jun 2011 15:21:12 +0300 Subject: OMAP: DSS2: DSI: Improve dsi_mux_pads parameters dsi_mux_pads() needs to know about the DSI HW module and the DSI lanes used. Split the function into two, enable and disable, which take necessary arguments, and add empty implementations for both. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c | 14 ++++++++++++++ drivers/video/omap2/dss/dsi.c | 42 +++++++++++++++++++++++++++++++----------- include/video/omapdss.h | 3 ++- 3 files changed, 47 insertions(+), 12 deletions(-) (limited to 'include/video') diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index c42df111c9d2..7c6011df80a8 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -74,6 +74,15 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { { "dss_hdmi", "omapdss_hdmi", -1 }, }; +static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask) +{ + return 0; +} + +static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) +{ +} + int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; @@ -96,6 +105,11 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); } + if (board_data->dsi_enable_pads == NULL) + board_data->dsi_enable_pads = omap_dsi_enable_pads; + if (board_data->dsi_disable_pads == NULL) + board_data->dsi_disable_pads = omap_dsi_disable_pads; + pdata.board_data = board_data; pdata.board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 713e1d9ac0ec..ae6bf1d46c97 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -274,7 +274,8 @@ struct dsi_data { struct clk *dss_clk; struct clk *sys_clk; - void (*dsi_mux_pads)(bool enable); + int (*enable_pads)(int dsi_id, unsigned lane_mask); + void (*disable_pads)(int dsi_id, unsigned lane_mask); struct dsi_clock_info current_cinfo; @@ -2355,6 +2356,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) return 0; } +static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) +{ + unsigned lanes = 0; + + if (dssdev->phy.dsi.clk_lane != 0) + lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); + if (dssdev->phy.dsi.data1_lane != 0) + lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); + if (dssdev->phy.dsi.data2_lane != 0) + lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1); + if (dssdev->phy.dsi.data3_lane != 0) + lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1); + if (dssdev->phy.dsi.data4_lane != 0) + lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1); + + return lanes; +} + static int dsi_cio_init(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -2365,8 +2384,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) DSSDBGF(); - if (dsi->dsi_mux_pads) - dsi->dsi_mux_pads(true); + r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); + if (r) + return r; dsi_enable_scp_clk(dsidev); @@ -2462,19 +2482,18 @@ err_cio_pwr: dsi_cio_disable_lane_override(dsidev); err_scp_clk_dom: dsi_disable_scp_clk(dsidev); - if (dsi->dsi_mux_pads) - dsi->dsi_mux_pads(false); + dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); return r; } -static void dsi_cio_uninit(struct platform_device *dsidev) +static void dsi_cio_uninit(struct omap_dss_device *dssdev) { + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); dsi_disable_scp_clk(dsidev); - if (dsi->dsi_mux_pads) - dsi->dsi_mux_pads(false); + dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); } static void dsi_config_tx_fifo(struct platform_device *dsidev, @@ -4161,7 +4180,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) return 0; err3: - dsi_cio_uninit(dsidev); + dsi_cio_uninit(dssdev); err2: dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); @@ -4190,7 +4209,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); - dsi_cio_uninit(dsidev); + dsi_cio_uninit(dssdev); dsi_pll_uninit(dsidev, disconnect_lanes); } @@ -4481,7 +4500,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev) dss_plat_data = dsidev->dev.platform_data; board_info = dss_plat_data->board_data; - dsi->dsi_mux_pads = board_info->dsi_mux_pads; + dsi->enable_pads = board_info->dsi_enable_pads; + dsi->disable_pads = board_info->dsi_disable_pads; spin_lock_init(&dsi->irq_lock); spin_lock_init(&dsi->errors_lock); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 3b55ef22f8db..c4d1d4ed909f 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -242,7 +242,8 @@ struct omap_dss_board_info { int num_devices; struct omap_dss_device **devices; struct omap_dss_device *default_device; - void (*dsi_mux_pads)(bool enable); + int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); + void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); }; #if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) -- cgit 1.4.1 From 8fa8031c542986746ed4dfbd1eb52358bc86000b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 16 Aug 2011 12:56:19 +0300 Subject: OMAP: DSS2: Handle manager change in apply Currently when changing the manager of an overlay, set_manager() directly calls dispc to set the overlay's destination. Change this to be more in line with other overlay configurations, and this will also remove the need to have dispc clocks enabled when calling set_manager(). A new field is added to overlay struct, "manager_changed". This is similar to "display_changed" field in manager struct, and is used to inform apply that the manager has changed and thus write to the registers is needed. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 4 +++- drivers/video/omap2/dss/dss.h | 2 -- drivers/video/omap2/dss/manager.c | 5 +++++ drivers/video/omap2/dss/overlay.c | 9 ++------- include/video/omapdss.h | 1 + 5 files changed, 11 insertions(+), 10 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9d9fbeb5362e..003227c82b3f 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -841,7 +841,7 @@ static void _dispc_set_color_mode(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } -void dispc_set_channel_out(enum omap_plane plane, +static void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel) { int shift; @@ -1860,6 +1860,8 @@ int dispc_setup_plane(enum omap_plane plane, _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); _dispc_setup_global_alpha(plane, global_alpha); + dispc_set_channel_out(plane, channel); + return 0; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index adeff04e964f..ff7ac35ec282 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -399,8 +399,6 @@ void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); -void dispc_set_channel_out(enum omap_plane plane, - enum omap_channel channel_out); void dispc_enable_gamma_table(bool enable); int dispc_setup_plane(enum omap_plane plane, diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 63674b054d35..a6a909ae8670 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1338,6 +1338,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) oc = &dss_cache.overlay_cache[ovl->id]; + if (ovl->manager_changed) { + ovl->manager_changed = false; + ovl->info_dirty = true; + } + if (!overlay_enabled(ovl)) { if (oc->enabled) { oc->enabled = false; diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index c84380c53c39..ab444036146b 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -516,6 +516,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, } ovl->manager = mgr; + ovl->manager_changed = true; /* XXX: When there is an overlay on a DSI manual update display, and * the overlay is first disabled, then moved to tv, and enabled, we @@ -529,15 +530,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, * Userspace workaround for this is to update the LCD after disabling * the overlay, but before moving the overlay to TV. */ - dispc_set_channel_out(ovl->id, mgr->id); return 0; } static int omap_dss_unset_manager(struct omap_overlay *ovl) { - int r; - if (!ovl->manager) { DSSERR("failed to detach overlay: manager not set\n"); return -EINVAL; @@ -548,11 +546,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl) return -EINVAL; } - r = ovl->wait_for_go(ovl); - if (r) - return r; - ovl->manager = NULL; + ovl->manager_changed = true; return 0; } diff --git a/include/video/omapdss.h b/include/video/omapdss.h index c4d1d4ed909f..ecde53f71bd2 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -333,6 +333,7 @@ struct omap_overlay { struct omap_overlay_manager *manager; struct omap_overlay_info info; + bool manager_changed; /* if true, info has been changed, but not applied() yet */ bool info_dirty; -- cgit 1.4.1 From 4a9e78abb76a2f1ddccab7098bdf73a2f095aaa6 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 15 Aug 2011 11:22:21 +0300 Subject: OMAP: DSS2: Remove support for non-DISPC overlays Remove support for non-DISPC overlays and overlay managers. The support to possibly have non-DISPC overlays and managers was made to make it possible to use CPU and/or sDMA to update RFBI or DSI command mode displays. It is ok to remove the support, because: - No one has used the feature. - Display update without DISPC is very slow, so it is debatable if the update would even be usable. - Removal cleans up code. - If such a feature is needed later, it is better implemented outside omapdss driver. Signed-off-by: Tomi Valkeinen Acked-by: Archit Taneja --- drivers/video/omap2/dss/dispc.c | 22 +---- drivers/video/omap2/dss/dsi.c | 190 +++----------------------------------- drivers/video/omap2/dss/manager.c | 47 +--------- drivers/video/omap2/dss/overlay.c | 8 +- drivers/video/omap2/dss/rfbi.c | 23 +---- include/video/omapdss.h | 7 +- 6 files changed, 22 insertions(+), 275 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 003227c82b3f..43dbfb1da778 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3058,9 +3058,6 @@ static void dispc_error_worker(struct work_struct *work) struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - if (ovl->id == 0) { dispc_enable_plane(ovl->id, 0); dispc_go(ovl->manager->id); @@ -3076,9 +3073,6 @@ static void dispc_error_worker(struct work_struct *work) struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - if (ovl->id == 1) { dispc_enable_plane(ovl->id, 0); dispc_go(ovl->manager->id); @@ -3094,9 +3088,6 @@ static void dispc_error_worker(struct work_struct *work) struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - if (ovl->id == 2) { dispc_enable_plane(ovl->id, 0); dispc_go(ovl->manager->id); @@ -3131,9 +3122,6 @@ static void dispc_error_worker(struct work_struct *work) struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - if (ovl->id != 0 && ovl->manager == manager) dispc_enable_plane(ovl->id, 0); } @@ -3170,9 +3158,6 @@ static void dispc_error_worker(struct work_struct *work) struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - if (ovl->id != 0 && ovl->manager == manager) dispc_enable_plane(ovl->id, 0); } @@ -3209,9 +3194,6 @@ static void dispc_error_worker(struct work_struct *work) struct omap_overlay *ovl; ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - if (ovl->id != 0 && ovl->manager == manager) dispc_enable_plane(ovl->id, 0); } @@ -3228,9 +3210,7 @@ static void dispc_error_worker(struct work_struct *work) for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { struct omap_overlay_manager *mgr; mgr = omap_dss_get_overlay_manager(i); - - if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) - mgr->device->driver->disable(mgr->device); + mgr->device->driver->disable(mgr->device); } } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c951a75e7021..bd0ff1d64497 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3648,161 +3648,6 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) enter_hs_mode_lat, exit_hs_mode_lat); } - -#define DSI_DECL_VARS \ - int __dsi_cb = 0; u32 __dsi_cv = 0; - -#define DSI_FLUSH(dsidev, ch) \ - if (__dsi_cb > 0) { \ - /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ - dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ - __dsi_cb = __dsi_cv = 0; \ - } - -#define DSI_PUSH(dsidev, ch, data) \ - do { \ - __dsi_cv |= (data) << (__dsi_cb * 8); \ - /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ - if (++__dsi_cb > 3) \ - DSI_FLUSH(dsidev, ch); \ - } while (0) - -static int dsi_update_screen_l4(struct omap_dss_device *dssdev, - int x, int y, int w, int h) -{ - /* Note: supports only 24bit colors in 32bit container */ - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - int first = 1; - int fifo_stalls = 0; - int max_dsi_packet_size; - int max_data_per_packet; - int max_pixels_per_packet; - int pixels_left; - int bytespp = dssdev->ctrl.pixel_size / 8; - int scr_width; - u32 __iomem *data; - int start_offset; - int horiz_inc; - int current_x; - struct omap_overlay *ovl; - - debug_irq = 0; - - DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", - x, y, w, h); - - ovl = dssdev->manager->overlays[0]; - - if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) - return -EINVAL; - - if (dssdev->ctrl.pixel_size != 24) - return -EINVAL; - - scr_width = ovl->info.screen_width; - data = ovl->info.vaddr; - - start_offset = scr_width * y + x; - horiz_inc = scr_width - w; - current_x = x; - - /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes - * in fifo */ - - /* When using CPU, max long packet size is TX buffer size */ - max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4; - - /* we seem to get better perf if we divide the tx fifo to half, - and while the other half is being sent, we fill the other half - max_dsi_packet_size /= 2; */ - - max_data_per_packet = max_dsi_packet_size - 4 - 1; - - max_pixels_per_packet = max_data_per_packet / bytespp; - - DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); - - pixels_left = w * h; - - DSSDBG("total pixels %d\n", pixels_left); - - data += start_offset; - - while (pixels_left > 0) { - /* 0x2c = write_memory_start */ - /* 0x3c = write_memory_continue */ - u8 dcs_cmd = first ? 0x2c : 0x3c; - int pixels; - DSI_DECL_VARS; - first = 0; - -#if 1 - /* using fifo not empty */ - /* TX_FIFO_NOT_EMPTY */ - while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) { - fifo_stalls++; - if (fifo_stalls > 0xfffff) { - DSSERR("fifo stalls overflow, pixels left %d\n", - pixels_left); - dsi_if_enable(dsidev, 0); - return -EIO; - } - udelay(1); - } -#elif 1 - /* using fifo emptiness */ - while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < - max_dsi_packet_size) { - fifo_stalls++; - if (fifo_stalls > 0xfffff) { - DSSERR("fifo stalls overflow, pixels left %d\n", - pixels_left); - dsi_if_enable(dsidev, 0); - return -EIO; - } - } -#else - while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, - 7, 0) + 1) * 4 == 0) { - fifo_stalls++; - if (fifo_stalls > 0xfffff) { - DSSERR("fifo stalls overflow, pixels left %d\n", - pixels_left); - dsi_if_enable(dsidev, 0); - return -EIO; - } - } -#endif - pixels = min(max_pixels_per_packet, pixels_left); - - pixels_left -= pixels; - - dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, - 1 + pixels * bytespp, 0); - - DSI_PUSH(dsidev, 0, dcs_cmd); - - while (pixels-- > 0) { - u32 pix = __raw_readl(data++); - - DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); - DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); - DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff); - - current_x++; - if (current_x == x+w) { - current_x = x; - data += horiz_inc; - } - } - - DSI_FLUSH(dsidev, 0); - } - - return 0; -} - static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) { @@ -3970,11 +3815,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, dsi_perf_mark_setup(dsidev); - if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { - dss_setup_partial_planes(dssdev, x, y, w, h, - enlarge_update_area); - dispc_set_lcd_size(dssdev->manager->id, *w, *h); - } + dss_setup_partial_planes(dssdev, x, y, w, h, + enlarge_update_area); + dispc_set_lcd_size(dssdev->manager->id, *w, *h); return 0; } @@ -3996,27 +3839,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev, * see rather obscure HW error happening, as DSS halts. */ BUG_ON(x % 2 == 1); - if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { - dsi->framedone_callback = callback; - dsi->framedone_data = data; - - dsi->update_region.x = x; - dsi->update_region.y = y; - dsi->update_region.w = w; - dsi->update_region.h = h; - dsi->update_region.device = dssdev; - - dsi_update_screen_dispc(dssdev, x, y, w, h); - } else { - int r; + dsi->framedone_callback = callback; + dsi->framedone_data = data; - r = dsi_update_screen_l4(dssdev, x, y, w, h); - if (r) - return r; + dsi->update_region.x = x; + dsi->update_region.y = y; + dsi->update_region.w = w; + dsi->update_region.h = h; + dsi->update_region.device = dssdev; - dsi_perf_show(dsidev, "L4"); - callback(0, data); - } + dsi_update_screen_dispc(dssdev, x, y, w, h); return 0; } diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index a6a909ae8670..72e041b3a66e 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1333,9 +1333,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - oc = &dss_cache.overlay_cache[ovl->id]; if (ovl->manager_changed) { @@ -1387,9 +1384,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) list_for_each_entry(mgr, &manager_list, list) { struct omap_dss_device *dssdev; - if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) - continue; - mc = &dss_cache.manager_cache[mgr->id]; if (mgr->device_changed) { @@ -1435,9 +1429,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) ovl = omap_dss_get_overlay(i); - if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) - continue; - oc = &dss_cache.overlay_cache[ovl->id]; if (!oc->enabled) @@ -1592,7 +1583,7 @@ int dss_init_overlay_managers(struct platform_device *pdev) mgr->enable = &dss_mgr_enable; mgr->disable = &dss_mgr_disable; - mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; + mgr->caps = 0; mgr->supported_displays = dss_feat_get_supported_displays(mgr->id); @@ -1609,42 +1600,6 @@ int dss_init_overlay_managers(struct platform_device *pdev) } } -#ifdef L4_EXAMPLE - { - int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) - { - DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); - - return 0; - } - - struct omap_overlay_manager *mgr; - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - - BUG_ON(mgr == NULL); - - mgr->name = "l4"; - mgr->supported_displays = - OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; - - mgr->set_device = &omap_dss_set_device; - mgr->unset_device = &omap_dss_unset_device; - mgr->apply = &omap_dss_mgr_apply_l4; - mgr->set_manager_info = &omap_dss_mgr_set_info; - mgr->get_manager_info = &omap_dss_mgr_get_info; - - dss_overlay_setup_l4_manager(mgr); - - omap_dss_add_overlay_manager(mgr); - - r = kobject_init_and_add(&mgr->kobj, &manager_ktype, - &pdev->dev.kobj, "managerl4"); - - if (r) - DSSERR("failed to create sysfs file\n"); - } -#endif - return 0; } diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index ab444036146b..0b21af95b48c 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -613,21 +613,19 @@ void dss_init_overlays(struct platform_device *pdev) case 0: ovl->name = "gfx"; ovl->id = OMAP_DSS_GFX; - ovl->caps = OMAP_DSS_OVL_CAP_DISPC; + ovl->caps = 0; ovl->info.global_alpha = 255; break; case 1: ovl->name = "vid1"; ovl->id = OMAP_DSS_VIDEO1; - ovl->caps = OMAP_DSS_OVL_CAP_SCALE | - OMAP_DSS_OVL_CAP_DISPC; + ovl->caps = OMAP_DSS_OVL_CAP_SCALE; ovl->info.global_alpha = 255; break; case 2: ovl->name = "vid2"; ovl->id = OMAP_DSS_VIDEO2; - ovl->caps = OMAP_DSS_OVL_CAP_SCALE | - OMAP_DSS_OVL_CAP_DISPC; + ovl->caps = OMAP_DSS_OVL_CAP_SCALE; ovl->info.global_alpha = 255; break; } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 50394badec15..b605066c176b 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, if (*w == 0 || *h == 0) return -EINVAL; - if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { - dss_setup_partial_planes(dssdev, x, y, w, h, true); - dispc_set_lcd_size(dssdev->manager->id, *w, *h); - } + dss_setup_partial_planes(dssdev, x, y, w, h, true); + dispc_set_lcd_size(dssdev->manager->id, *w, *h); return 0; } @@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h, void (*callback)(void *), void *data) { - if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { - rfbi_transfer_area(dssdev, w, h, callback, data); - } else { - struct omap_overlay *ovl; - void __iomem *addr; - int scr_width; - - ovl = dssdev->manager->overlays[0]; - scr_width = ovl->info.screen_width; - addr = ovl->info.vaddr; - - omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); - - callback(data); - } - + rfbi_transfer_area(dssdev, w, h, callback, data); return 0; } EXPORT_SYMBOL(omap_rfbi_update); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index ecde53f71bd2..cb1ff1a6b5ee 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -162,11 +162,10 @@ enum omap_dss_rotation_angle { enum omap_overlay_caps { OMAP_DSS_OVL_CAP_SCALE = 1 << 0, - OMAP_DSS_OVL_CAP_DISPC = 1 << 1, }; enum omap_overlay_manager_caps { - OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, + OMAP_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */ }; enum omap_dss_clk_source { @@ -325,7 +324,7 @@ struct omap_overlay { /* static fields */ const char *name; - int id; + enum omap_plane id; enum omap_color_mode supported_modes; enum omap_overlay_caps caps; @@ -368,7 +367,7 @@ struct omap_overlay_manager { /* static fields */ const char *name; - int id; + enum omap_channel id; enum omap_overlay_manager_caps caps; int num_overlays; struct omap_overlay **overlays; -- cgit 1.4.1 From f6dc815098bde08c09fd1219e0f77663f8a9a6c7 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 15 Aug 2011 15:18:20 +0300 Subject: OMAP: DSS2: Add GLOBAL_ALPHA & PRE_MULT_ALPHA to ovl caps Add OMAP_DSS_OVL_CAP_GLOBAL_ALPHA and OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA to overlay capabilities. Use these instead of FEAT_GLOBAL_ALPHA, FEAT_GLOBAL_ALPHA_VID1 and FEAT_PRE_MULT_ALPHA in code. Remove FEAT_GLOBAL_ALPHA_VID1 and FEAT_PRE_MULT_ALPHA which are no longer used. FEAT_GLOBAL_ALPHA is still used to decide if the HW has global alpha register. Signed-off-by: Tomi Valkeinen Acked-by: Archit Taneja --- drivers/video/omap2/dss/dispc.c | 13 ++++--------- drivers/video/omap2/dss/dss_features.c | 27 +++++++++++++++------------ drivers/video/omap2/dss/dss_features.h | 2 -- drivers/video/omap2/dss/overlay.c | 23 ++++++----------------- include/video/omapdss.h | 2 ++ 5 files changed, 27 insertions(+), 40 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 2a0fb5ca13d6..343b99acf523 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -725,11 +725,9 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) { - if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) - return; + struct omap_overlay *ovl = omap_dss_get_overlay(plane); - if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && - plane == OMAP_DSS_VIDEO1) + if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) return; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); @@ -739,12 +737,9 @@ static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) { static const unsigned shifts[] = { 0, 8, 16, }; int shift; + struct omap_overlay *ovl = omap_dss_get_overlay(plane); - if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) - return; - - if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && - plane == OMAP_DSS_VIDEO1) + if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) return; shift = shifts[plane]; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 6bf508de3c32..b63c5f8d9151 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -225,35 +225,38 @@ static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { /* OMAP_DSS_GFX */ - 0, + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, /* OMAP_DSS_VIDEO1 */ OMAP_DSS_OVL_CAP_SCALE, /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE, + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, }; static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { /* OMAP_DSS_GFX */ - 0, + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, /* OMAP_DSS_VIDEO1 */ OMAP_DSS_OVL_CAP_SCALE, /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE, + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, }; static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { /* OMAP_DSS_GFX */ - 0, + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, /* OMAP_DSS_VIDEO1 */ - OMAP_DSS_OVL_CAP_SCALE, + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, /* OMAP_DSS_VIDEO2 */ - OMAP_DSS_OVL_CAP_SCALE, + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, }; static const char * const omap2_dss_clk_source_names[] = { @@ -359,7 +362,7 @@ static const struct omap_dss_features omap3630_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | + FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | @@ -383,8 +386,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), .has_feature = - FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | - FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | + FEAT_GLOBAL_ALPHA | + FEAT_MGR_LCD2 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | @@ -407,8 +410,8 @@ static const struct omap_dss_features omap4_dss_features = { .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), .has_feature = - FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | - FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | + FEAT_GLOBAL_ALPHA | + FEAT_MGR_LCD2 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index fd091967c950..4271e9661c90 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -28,8 +28,6 @@ /* DSS has feature id */ enum dss_feat_id { FEAT_GLOBAL_ALPHA = 1 << 0, - FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, - FEAT_PRE_MULT_ALPHA = 1 << 2, FEAT_LCDENABLEPOL = 1 << 3, FEAT_LCDENABLESIGNAL = 1 << 4, FEAT_PCKFREEENABLE = 1 << 5, diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 777e23690bd1..62691d0a8aae 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -248,7 +248,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, u8 alpha; struct omap_overlay_info info; - if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) + if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) return -ENODEV; r = kstrtou8(buf, 0, &alpha); @@ -257,14 +257,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, ovl->get_overlay_info(ovl, &info); - /* Video1 plane does not support global alpha - * to always make it 255 completely opaque - */ - if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && - ovl->id == OMAP_DSS_VIDEO1) - info.global_alpha = 255; - else - info.global_alpha = alpha; + info.global_alpha = alpha; r = ovl->set_overlay_info(ovl, &info); if (r) @@ -293,20 +286,16 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, u8 alpha; struct omap_overlay_info info; + if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) + return -ENODEV; + r = kstrtou8(buf, 0, &alpha); if (r) return r; ovl->get_overlay_info(ovl, &info); - /* only GFX and Video2 plane support pre alpha multiplied - * set zero for Video1 plane - */ - if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && - ovl->id == OMAP_DSS_VIDEO1) - info.pre_mult_alpha = 0; - else - info.pre_mult_alpha = alpha; + info.pre_mult_alpha = alpha; r = ovl->set_overlay_info(ovl, &info); if (r) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index cb1ff1a6b5ee..ddd5bd06b785 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -162,6 +162,8 @@ enum omap_dss_rotation_angle { enum omap_overlay_caps { OMAP_DSS_OVL_CAP_SCALE = 1 << 0, + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1, + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2, }; enum omap_overlay_manager_caps { -- cgit 1.4.1 From 7e951ee9955f3df0c41e523a199cc3b9372cdb9f Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 22 Jul 2011 12:45:04 +0530 Subject: OMAP: DSS2: Create enum for DSI operation modes Create an enum for DSI operation modes, use this to set the capabilities of the device in dsi_init_display(). Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 7 ++++--- include/video/omapdss.h | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index bdc2c9d25784..d3bffe8b2a38 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4123,9 +4123,10 @@ int dsi_init_display(struct omap_dss_device *dssdev) DSSDBG("DSI init\n"); - /* XXX these should be figured out dynamically */ - dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | - OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { + dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | + OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; + } if (dsi->vdds_dsi_reg == NULL) { struct regulator *vdds_dsi; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index ddd5bd06b785..aeadbc880e38 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -129,6 +129,11 @@ enum omap_dss_venc_type { OMAP_DSS_VENC_TYPE_SVIDEO, }; +enum omap_dss_dsi_mode { + OMAP_DSS_DSI_CMD_MODE = 0, + OMAP_DSS_DSI_VIDEO_MODE, +}; + enum omap_display_caps { OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1, @@ -480,6 +485,8 @@ struct omap_dss_device { int acb; /* ac-bias pin frequency */ enum omap_panel_config config; + + enum omap_dss_dsi_mode dsi_mode; } panel; struct { -- cgit 1.4.1 From 6ff8aa3182db248db4d91e574254316025c0243c Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 25 Aug 2011 18:35:58 +0530 Subject: OMAP: DSS2: DSI: Introduce generic write functions Intoduce enum "dss_dsi_content_type" to differentiate between DCS and generic content types. Introduce short and long packet write functions which use generic Processor-to-Peripheral transaction types. These are needed by some devices which may not support corresponding DCS commands. Create common write functions which allow code reuse between DCS and generic write functions. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 84 ++++++++++++++++++++++++++++++++++++------- drivers/video/omap2/dss/dss.h | 5 +++ include/video/omapdss.h | 12 +++++-- 3 files changed, 87 insertions(+), 14 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d3bffe8b2a38..bb5588932b02 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3065,38 +3065,60 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) } EXPORT_SYMBOL(dsi_vc_send_null); -int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, - u8 *data, int len) +static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, + int channel, u8 *data, int len, enum dss_dsi_content_type type) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); int r; - BUG_ON(len == 0); - - if (len == 1) { + if (len == 0) { + BUG_ON(type == DSS_DSI_CONTENT_DCS); r = dsi_vc_send_short(dsidev, channel, + MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0); + } else if (len == 1) { + r = dsi_vc_send_short(dsidev, channel, + type == DSS_DSI_CONTENT_GENERIC ? + MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM : MIPI_DSI_DCS_SHORT_WRITE, data[0], 0); } else if (len == 2) { r = dsi_vc_send_short(dsidev, channel, + type == DSS_DSI_CONTENT_GENERIC ? + MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM : MIPI_DSI_DCS_SHORT_WRITE_PARAM, data[0] | (data[1] << 8), 0); } else { - /* 0x39 = DCS Long Write */ - r = dsi_vc_send_long(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE, - data, len, 0); + r = dsi_vc_send_long(dsidev, channel, + type == DSS_DSI_CONTENT_GENERIC ? + MIPI_DSI_GENERIC_LONG_WRITE : + MIPI_DSI_DCS_LONG_WRITE, data, len, 0); } return r; } + +int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, + u8 *data, int len) +{ + return dsi_vc_write_nosync_common(dssdev, channel, data, len, + DSS_DSI_CONTENT_DCS); +} EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); -int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, - int len) +int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, + u8 *data, int len) +{ + return dsi_vc_write_nosync_common(dssdev, channel, data, len, + DSS_DSI_CONTENT_GENERIC); +} +EXPORT_SYMBOL(dsi_vc_generic_write_nosync); + +static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel, + u8 *data, int len, enum dss_dsi_content_type type) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); int r; - r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); + r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); if (r) goto err; @@ -3114,18 +3136,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, return 0; err: - DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", + DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n", channel, data[0], len); return r; } + +int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, + int len) +{ + return dsi_vc_write_common(dssdev, channel, data, len, + DSS_DSI_CONTENT_DCS); +} EXPORT_SYMBOL(dsi_vc_dcs_write); +int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, + int len) +{ + return dsi_vc_write_common(dssdev, channel, data, len, + DSS_DSI_CONTENT_GENERIC); +} +EXPORT_SYMBOL(dsi_vc_generic_write); + int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) { return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); } EXPORT_SYMBOL(dsi_vc_dcs_write_0); +int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel) +{ + return dsi_vc_generic_write(dssdev, channel, NULL, 0); +} +EXPORT_SYMBOL(dsi_vc_generic_write_0); + int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, u8 param) { @@ -3136,6 +3179,23 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, } EXPORT_SYMBOL(dsi_vc_dcs_write_1); +int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, + u8 param) +{ + return dsi_vc_generic_write(dssdev, channel, ¶m, 1); +} +EXPORT_SYMBOL(dsi_vc_generic_write_1); + +int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, + u8 param1, u8 param2) +{ + u8 buf[2]; + buf[0] = param1; + buf[1] = param2; + return dsi_vc_generic_write(dssdev, channel, buf, 2); +} +EXPORT_SYMBOL(dsi_vc_generic_write_2); + int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, u8 *buf, int buflen) { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index a095a62c64e8..3ec8dd7066a2 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select { DSS_HDMI_M_PCLK = 1, }; +enum dss_dsi_content_type { + DSS_DSI_CONTENT_DCS, + DSS_DSI_CONTENT_GENERIC, +}; + struct dss_clock_info { /* rates that we get with dividers below */ unsigned long fck; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index aeadbc880e38..49ffdd201c2d 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -225,12 +225,20 @@ void dsi_bus_lock(struct omap_dss_device *dssdev); void dsi_bus_unlock(struct omap_dss_device *dssdev); int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, int len); -int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, - u8 dcs_cmd); +int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, + int len); +int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd); +int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel); int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, u8 param); +int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, + u8 param); +int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, + u8 param1, u8 param2); int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, u8 *data, int len); +int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, + u8 *data, int len); int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, u8 *buf, int buflen); int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, -- cgit 1.4.1 From 5c716a04ed1f5b8a3e1a8953b71f89441a70d1d4 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 22 Aug 2011 14:44:27 +0530 Subject: OMAP: DSS2: DSI: Remove functions dsi_vc_dcs_read_1() and dsi_vc_dcs_read_2() Remove functions dsi_vc_dcs_read_1() and dsi_vc_dcs_read_2(), these are used when the panel is expected to return 1 and 2 bytes respecitvely. This was manily used for debugging purposes. These functions should be implemented in the panel driver if needed. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 38 -------------------------------------- include/video/omapdss.h | 4 ---- 2 files changed, 42 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index bb5588932b02..82516471b64f 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3307,44 +3307,6 @@ err: } EXPORT_SYMBOL(dsi_vc_dcs_read); -int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, - u8 *data) -{ - int r; - - r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); - - if (r < 0) - return r; - - if (r != 1) - return -EIO; - - return 0; -} -EXPORT_SYMBOL(dsi_vc_dcs_read_1); - -int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, - u8 *data1, u8 *data2) -{ - u8 buf[2]; - int r; - - r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); - - if (r < 0) - return r; - - if (r != 2) - return -EIO; - - *data1 = buf[0]; - *data2 = buf[1]; - - return 0; -} -EXPORT_SYMBOL(dsi_vc_dcs_read_2); - int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, u16 len) { diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 49ffdd201c2d..a8a43de3dd81 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -241,10 +241,6 @@ int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, u8 *data, int len); int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, u8 *buf, int buflen); -int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, - u8 *data); -int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, - u8 *data1, u8 *data2); int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, u16 len); int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); -- cgit 1.4.1 From b3b89c05cbd9869cfd6d4e352293a2e7e3bffc6e Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 30 Aug 2011 16:07:39 +0530 Subject: OMAP: DSS2: DSI: Introduce generic read functions Introduce read functions which use generic Processor-to-Peripheral transaction types. These are needed by some devices which may not support corresponding DCS commands. Add function dsi_vc_generic_send_read_request() which can send a short packet with 0, 1 or 2 bytes of request data and the corresponding generic data type. Rename function dsi_vc_dcs_read_rx_fifo() to dsi_vc_read_rx_fifo() and modify it to take the enum "dss_dsi_content_type" as an argument to use either DCS or GENERIC Peripheral-to-Processor transaction types while parsing data read from the device. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 146 +++++++++++++++++++++++++++++++++++++++--- include/video/omapdss.h | 6 ++ 2 files changed, 142 insertions(+), 10 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c26a91435e50..20cad1b529bd 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3217,8 +3217,44 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, return 0; } -static int dsi_vc_dcs_read_rx_fifo(struct platform_device *dsidev, int channel, - u8 *buf, int buflen) +static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, + int channel, u8 *reqdata, int reqlen) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + u16 data; + u8 data_type; + int r; + + if (dsi->debug_read) + DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n", + channel, reqlen); + + if (reqlen == 0) { + data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; + data = 0; + } else if (reqlen == 1) { + data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; + data = reqdata[0]; + } else if (reqlen == 2) { + data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; + data = reqdata[0] | (reqdata[1] << 8); + } else { + BUG(); + } + + r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); + if (r) { + DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)" + " failed\n", channel, reqlen); + return r; + } + + return 0; +} + +static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, + u8 *buf, int buflen, enum dss_dsi_content_type type) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u32 val; @@ -3242,10 +3278,14 @@ static int dsi_vc_dcs_read_rx_fifo(struct platform_device *dsidev, int channel, r = -EIO; goto err; - } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) { + } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? + MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE : + MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) { u8 data = FLD_GET(val, 15, 8); if (dsi->debug_read) - DSSDBG("\tDCS short response, 1 byte: %02x\n", data); + DSSDBG("\t%s short response, 1 byte: %02x\n", + type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : + "DCS", data); if (buflen < 1) { r = -EIO; @@ -3255,10 +3295,14 @@ static int dsi_vc_dcs_read_rx_fifo(struct platform_device *dsidev, int channel, buf[0] = data; return 1; - } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) { + } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? + MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE : + MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) { u16 data = FLD_GET(val, 23, 8); if (dsi->debug_read) - DSSDBG("\tDCS short response, 2 byte: %04x\n", data); + DSSDBG("\t%s short response, 2 byte: %04x\n", + type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : + "DCS", data); if (buflen < 2) { r = -EIO; @@ -3269,11 +3313,15 @@ static int dsi_vc_dcs_read_rx_fifo(struct platform_device *dsidev, int channel, buf[1] = (data >> 8) & 0xff; return 2; - } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) { + } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? + MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE : + MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) { int w; int len = FLD_GET(val, 23, 8); if (dsi->debug_read) - DSSDBG("\tDCS long response, len %d\n", len); + DSSDBG("\t%s long response, len %d\n", + type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : + "DCS", len); if (len > buflen) { r = -EIO; @@ -3309,7 +3357,8 @@ static int dsi_vc_dcs_read_rx_fifo(struct platform_device *dsidev, int channel, BUG(); err: - DSSERR("dsi_vc_dcs_read_rx_fifo(ch %d) failed\n", channel); + DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, + type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); return r; } @@ -3328,7 +3377,8 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, if (r) goto err; - r = dsi_vc_dcs_read_rx_fifo(dsidev, channel, buf, buflen); + r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, + DSS_DSI_CONTENT_DCS); if (r < 0) goto err; @@ -3344,6 +3394,82 @@ err: } EXPORT_SYMBOL(dsi_vc_dcs_read); +static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel, + u8 *reqdata, int reqlen, u8 *buf, int buflen) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + int r; + + r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); + if (r) + return r; + + r = dsi_vc_send_bta_sync(dssdev, channel); + if (r) + return r; + + r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, + DSS_DSI_CONTENT_GENERIC); + if (r < 0) + return r; + + if (r != buflen) { + r = -EIO; + return r; + } + + return 0; +} + +int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, + int buflen) +{ + int r; + + r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen); + if (r) { + DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel); + return r; + } + + return 0; +} +EXPORT_SYMBOL(dsi_vc_generic_read_0); + +int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, + u8 *buf, int buflen) +{ + int r; + + r = dsi_vc_generic_read(dssdev, channel, ¶m, 1, buf, buflen); + if (r) { + DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel); + return r; + } + + return 0; +} +EXPORT_SYMBOL(dsi_vc_generic_read_1); + +int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, + u8 param1, u8 param2, u8 *buf, int buflen) +{ + int r; + u8 reqdata[2]; + + reqdata[0] = param1; + reqdata[1] = param2; + + r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen); + if (r) { + DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel); + return r; + } + + return 0; +} +EXPORT_SYMBOL(dsi_vc_generic_read_2); + int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, u16 len) { diff --git a/include/video/omapdss.h b/include/video/omapdss.h index a8a43de3dd81..abe8b1e51529 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -241,6 +241,12 @@ int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, u8 *data, int len); int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, u8 *buf, int buflen); +int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, + int buflen); +int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, + u8 *buf, int buflen); +int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, + u8 param1, u8 param2, u8 *buf, int buflen); int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, u16 len); int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); -- cgit 1.4.1 From a3b3cc2b883aac18a3388a405db809a99d66e3cf Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 8 Sep 2011 18:42:16 +0530 Subject: OMAP: DSS2: Create an enum for DSI pixel formats Currently, DSI pixel info is only represented by the pixel size in bits using the pixel_size parameter in omap_dss_device struct's ctrl member. This is not sufficient information for DSI video mode usage, as two of the supported formats(RGB666 loosely packed, and RGB888) have the same pixel container size, but different data_type values for the video mode packet header. Create enum "omap_dss_dsi_pixel_format" which describes the pixel data format the panel is configured for. Create helper function dsi_get_pixel_size() which returns the pixel size of the given pixel format. Modify functions omapdss_default_get_recommended_bpp() and dss_use_replication() to use dsi_get_pixel_size(). Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 2 +- drivers/video/omap2/dss/display.c | 10 ++++++++-- drivers/video/omap2/dss/dsi.c | 24 ++++++++++++++++++++---- drivers/video/omap2/dss/dss.h | 7 +++++++ include/video/omapdss.h | 8 ++++++++ 5 files changed, 44 insertions(+), 7 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 7675687c6fe4..ddc696d52abe 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -976,7 +976,7 @@ static int taal_probe(struct omap_dss_device *dssdev) dssdev->panel.config = OMAP_DSS_LCD_TFT; dssdev->panel.timings = panel_config->timings; - dssdev->ctrl.pixel_size = 24; + dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; td = kzalloc(sizeof(*td), GFP_KERNEL); if (!td) { diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 2c6e2bc5e207..be331dc5a61b 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -299,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) return 16; case OMAP_DISPLAY_TYPE_DBI: - case OMAP_DISPLAY_TYPE_DSI: if (dssdev->ctrl.pixel_size == 24) return 24; else return 16; + case OMAP_DISPLAY_TYPE_DSI: + if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) + return 24; + else + return 16; case OMAP_DISPLAY_TYPE_VENC: case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_HDMI: @@ -339,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev, bpp = 24; break; case OMAP_DISPLAY_TYPE_DBI: - case OMAP_DISPLAY_TYPE_DSI: bpp = dssdev->ctrl.pixel_size; break; + case OMAP_DISPLAY_TYPE_DSI: + bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); + break; default: BUG(); } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index c2c2fa778b39..2b7d17b7812c 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -422,6 +422,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev, return value; } +u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) +{ + switch (fmt) { + case OMAP_DSS_DSI_FMT_RGB888: + case OMAP_DSS_DSI_FMT_RGB666: + return 24; + case OMAP_DSS_DSI_FMT_RGB666_PACKED: + return 18; + case OMAP_DSS_DSI_FMT_RGB565: + return 16; + default: + BUG(); + } +} + #ifdef DEBUG static void dsi_perf_mark_setup(struct platform_device *dsidev) { @@ -438,6 +453,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev) static void dsi_perf_show(struct platform_device *dsidev, const char *name) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + struct omap_dss_device *dssdev = dsi->update_region.device; ktime_t t, setup_time, trans_time; u32 total_bytes; u32 setup_us, trans_us, total_us; @@ -461,7 +477,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) total_bytes = dsi->update_region.w * dsi->update_region.h * - dsi->update_region.device->ctrl.pixel_size / 8; + dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " "%u bytes, %u kbytes/sec\n", @@ -3689,7 +3705,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); - switch (dssdev->ctrl.pixel_size) { + switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { case 16: buswidth = 0; break; @@ -3814,7 +3830,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); - bytespp = dssdev->ctrl.pixel_size / 8; + bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; bytespl = w * bytespp; bytespf = bytespl * h; @@ -4023,7 +4039,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); dispc_mgr_set_tft_data_lines(dssdev->manager->id, - dssdev->ctrl.pixel_size); + dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); { struct omap_video_timings timings = { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index f4196f5d7001..eb716521d775 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -282,6 +282,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, int dsi_init_display(struct omap_dss_device *display); void dsi_irq_handler(void); +u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); + unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); int dsi_pll_set_clock_div(struct platform_device *dsidev, struct dsi_clock_info *cinfo); @@ -312,6 +314,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev) static inline void dsi_runtime_put(struct platform_device *dsidev) { } +static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) +{ + WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__); + return 0; +} static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) { WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index abe8b1e51529..89a9c290cf5d 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -129,6 +129,13 @@ enum omap_dss_venc_type { OMAP_DSS_VENC_TYPE_SVIDEO, }; +enum omap_dss_dsi_pixel_format { + OMAP_DSS_DSI_FMT_RGB888, + OMAP_DSS_DSI_FMT_RGB666, + OMAP_DSS_DSI_FMT_RGB666_PACKED, + OMAP_DSS_DSI_FMT_RGB565, +}; + enum omap_dss_dsi_mode { OMAP_DSS_DSI_CMD_MODE = 0, OMAP_DSS_DSI_VIDEO_MODE, @@ -496,6 +503,7 @@ struct omap_dss_device { enum omap_panel_config config; + enum omap_dss_dsi_pixel_format dsi_pix_fmt; enum omap_dss_dsi_mode dsi_mode; } panel; -- cgit 1.4.1 From 8af6ff0107f0720b8fbf4feca7031d3e36c2fa11 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 5 Sep 2011 16:48:27 +0530 Subject: OMAP: DSS2: DSI Video mode support Add initial support for DSI video mode panels: - Add a new structure omap_dss_dsi_videomode_data in the member "panel" in omap_dss_device struct. This allows panel driver to configure dsi video_mode specific parameters. - Configure basic DSI video mode timing parameters: HBP, HFP, HSA, VBP, VFP, VSA, TL and VACT. - Configure DSI protocol engine registers for video_mode support. - Introduce functions dsi_video_mode_enable() and dsi_video_mode_disable() which enable/disable video mode for a given virtual channel and a given pixel format type. Things left for later - Add functions to check for errors in video mode timings provided by panel. - Configure timing registers required for command mode interleaving. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 260 +++++++++++++++++++++++++++++++++++++----- include/video/omapdss.h | 32 ++++++ 2 files changed, 263 insertions(+), 29 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 77aca3e9a058..43c04a9889c4 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -132,7 +132,7 @@ struct dsi_reg { u16 idx; }; #define DSI_IRQ_TA_TIMEOUT (1 << 20) #define DSI_IRQ_ERROR_MASK \ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ - DSI_IRQ_TA_TIMEOUT) + DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) #define DSI_IRQ_CHANNEL_MASK 0xf /* Virtual channel interrupts */ @@ -2472,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) dsi_cio_timings(dsidev); + if (dssdev->panel.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->ulps_enabled = false; DSSDBG("CIO init done\n"); @@ -2496,6 +2502,9 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev) struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + /* DDR_CLK_ALWAYS_ON */ + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); + dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); dsi_disable_scp_clk(dsidev); dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); @@ -2799,6 +2808,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, dsi_if_enable(dsidev, 1); 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) + dsi_vc_send_null(dssdev, channel); } EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); @@ -3682,6 +3695,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, ticks, x4 ? " x4" : "", x16 ? " x16" : "", (total_ticks * 1000) / (fck / 1000 / 1000)); } + +static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + 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); + unsigned line_buf_size = dsi_get_line_buf_size(dsidev); + struct omap_video_timings *timings = &dssdev->panel.timings; + /* + * Don't use line buffers if width is greater than the video + * port's line buffer size + */ + if (line_buf_size <= timings->x_res * bpp / 8) + num_line_buffers = 0; + else + num_line_buffers = 2; + } else { + /* Use maximum number of line buffers in command mode */ + num_line_buffers = 2; + } + + /* LINE_BUFFER */ + REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); +} + +static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol; + int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol; + int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol; + bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; + bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; + u32 r; + + r = dsi_read_reg(dsidev, DSI_CTRL); + r = FLD_MOD(r, de_pol, 9, 9); /* VP_DE_POL */ + r = FLD_MOD(r, hsync_pol, 10, 10); /* VP_HSYNC_POL */ + r = FLD_MOD(r, vsync_pol, 11, 11); /* VP_VSYNC_POL */ + r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ + r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ + r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ + r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ + dsi_write_reg(dsidev, DSI_CTRL, r); +} + +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; + u32 r; + + /* + * 0 = TX FIFO packets sent or LPS in corresponding blanking periods + * 1 = Long blanking packets are sent in corresponding blanking periods + */ + r = dsi_read_reg(dsidev, DSI_CTRL); + r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */ + r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */ + r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */ + r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */ + dsi_write_reg(dsidev, DSI_CTRL, r); +} + static int dsi_proto_config(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -3725,7 +3807,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ - r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { @@ -3736,6 +3817,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) dsi_write_reg(dsidev, DSI_CTRL, r); + dsi_config_vp_num_line_buffers(dssdev); + + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { + dsi_config_vp_sync_events(dssdev); + dsi_config_blanking_modes(dssdev); + } + dsi_vc_initial_config(dsidev, 0); dsi_vc_initial_config(dsidev, 1); dsi_vc_initial_config(dsidev, 2); @@ -3754,6 +3842,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) unsigned ddr_clk_pre, ddr_clk_post; unsigned enter_hs_mode_lat, exit_hs_mode_lat; unsigned ths_eot; + int ndl = dsi_get_num_data_lanes_dssdev(dssdev); u32 r; r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); @@ -3776,7 +3865,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) /* min 60ns + 52*UI */ tclk_post = ns2ddr(dsidev, 60) + 26; - ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); + ths_eot = DIV_ROUND_UP(4, ndl); ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, 4); @@ -3806,7 +3895,114 @@ static void dsi_proto_timings(struct omap_dss_device *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) { + /* 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 tl, t_he, width_bytes; + + t_he = hsync_end ? + ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; + + width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); + + /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ + tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + + DIV_ROUND_UP(width_bytes + 6, ndl) + hbp; + + DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, + hfp, hsync_end ? hsa : 0, tl); + DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, + vsa, timings->y_res); + + r = dsi_read_reg(dsidev, DSI_VM_TIMING1); + r = FLD_MOD(r, hbp, 11, 0); /* HBP */ + r = FLD_MOD(r, hfp, 23, 12); /* HFP */ + r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */ + dsi_write_reg(dsidev, DSI_VM_TIMING1, r); + + r = dsi_read_reg(dsidev, DSI_VM_TIMING2); + r = FLD_MOD(r, vbp, 7, 0); /* VBP */ + r = FLD_MOD(r, vfp, 15, 8); /* VFP */ + r = FLD_MOD(r, vsa, 23, 16); /* VSA */ + r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */ + dsi_write_reg(dsidev, DSI_VM_TIMING2, r); + + r = dsi_read_reg(dsidev, DSI_VM_TIMING3); + r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */ + r = FLD_MOD(r, tl, 31, 16); /* TL */ + dsi_write_reg(dsidev, DSI_VM_TIMING3, r); + } +} + +int dsi_video_mode_enable(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); + u8 data_type; + u16 word_count; + + switch (dssdev->panel.dsi_pix_fmt) { + case OMAP_DSS_DSI_FMT_RGB888: + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; + break; + case OMAP_DSS_DSI_FMT_RGB666: + data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; + break; + case OMAP_DSS_DSI_FMT_RGB666_PACKED: + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; + break; + case OMAP_DSS_DSI_FMT_RGB565: + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; + break; + default: + BUG(); + }; + + dsi_if_enable(dsidev, false); + dsi_vc_enable(dsidev, channel, false); + + /* 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); + + dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); + + dsi_vc_enable(dsidev, channel, true); + dsi_if_enable(dsidev, true); + + dssdev->manager->enable(dssdev->manager); + + return 0; } +EXPORT_SYMBOL(dsi_video_mode_enable); + +void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + + dsi_if_enable(dsidev, false); + dsi_vc_enable(dsidev, channel, false); + + /* MODE, 0 = command mode */ + REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); + + dsi_vc_enable(dsidev, channel, true); + dsi_if_enable(dsidev, true); + + dssdev->manager->disable(dssdev->manager); +} +EXPORT_SYMBOL(dsi_video_mode_disable); static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) @@ -4019,28 +4215,9 @@ EXPORT_SYMBOL(omap_dsi_update); static int dsi_display_init_dispc(struct omap_dss_device *dssdev) { int r; - u32 irq; - - irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? - DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; - - r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, - irq); - if (r) { - DSSERR("can't get FRAMEDONE irq\n"); - return r; - } - - dispc_mgr_set_lcd_display_type(dssdev->manager->id, - OMAP_DSS_LCD_DISPLAY_TFT); - - dispc_mgr_enable_stallmode(dssdev->manager->id, true); - dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); - - dispc_mgr_set_tft_data_lines(dssdev->manager->id, - dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); - { + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { + u32 irq; struct omap_video_timings timings = { .hsw = 1, .hfp = 1, @@ -4050,21 +4227,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) .vbp = 0, }; + irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? + DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; + + r = omap_dispc_register_isr(dsi_framedone_irq_callback, + (void *) dssdev, irq); + if (r) { + DSSERR("can't get FRAMEDONE irq\n"); + return r; + } + + dispc_mgr_enable_stallmode(dssdev->manager->id, true); + dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); + dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); + } else { + dispc_mgr_enable_stallmode(dssdev->manager->id, false); + dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); + + dispc_mgr_set_lcd_timings(dssdev->manager->id, + &dssdev->panel.timings); } + dispc_mgr_set_lcd_display_type(dssdev->manager->id, + OMAP_DSS_LCD_DISPLAY_TFT); + dispc_mgr_set_tft_data_lines(dssdev->manager->id, + dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); return 0; } static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) { - u32 irq; + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { + u32 irq; - irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? - DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; + irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? + DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; - omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, - irq); + omap_dispc_unregister_isr(dsi_framedone_irq_callback, + (void *) dssdev, irq); + } } static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 89a9c290cf5d..44f423ff64bd 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -228,6 +228,35 @@ void rfbi_bus_lock(void); void rfbi_bus_unlock(void); /* DSI */ + +struct omap_dss_dsi_videomode_data { + /* DSI video mode blanking data */ + /* Unit: byte clock cycles */ + u16 hsa; + u16 hfp; + u16 hbp; + /* Unit: line clocks */ + u16 vsa; + u16 vfp; + u16 vbp; + + /* DSI blanking modes */ + int blanking_mode; + int hsa_blanking_mode; + int hbp_blanking_mode; + int hfp_blanking_mode; + + /* Video port sync events */ + int vp_de_pol; + int vp_hsync_pol; + int vp_vsync_pol; + bool vp_vsync_end; + bool vp_hsync_end; + + bool ddr_clk_always_on; + int window_sync; +}; + void dsi_bus_lock(struct omap_dss_device *dssdev); void dsi_bus_unlock(struct omap_dss_device *dssdev); int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, @@ -258,6 +287,8 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, u16 len); int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); +int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel); +void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel); /* Board specific data */ struct omap_dss_board_info { @@ -505,6 +536,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; } panel; struct { -- cgit 1.4.1 From b44e45825dbe30f32c770b98c38555b6bd331760 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 22 Aug 2011 13:16:24 +0300 Subject: OMAP: DSS2: HDMI: change regn definition regn divider is currently programmed to the registers without change, but when calculating clock frequencies it is used as regn+1. To make this similar to how DSI handles the dividers this patch changes the regn value to be used as such for calculations, but the value programmed to registers is regn-1. This simplifies the clock frequency calculations, makes it similar to DSI, and also allows us to use regn value 0 as undefined. Cc: Mythri P K Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/hdmi.c | 6 +++--- drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 2 +- include/video/omapdss.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'include/video') diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 52731b5e10f0..4752137b226a 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -60,7 +60,7 @@ #define OMAP_HDMI_TIMINGS_NB 34 -#define HDMI_DEFAULT_REGN 15 +#define HDMI_DEFAULT_REGN 16 #define HDMI_DEFAULT_REGM2 1 static struct { @@ -426,7 +426,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, else pi->regn = dssdev->clocks.hdmi.regn; - refclk = clkin / (pi->regn + 1); + refclk = clkin / pi->regn; /* * multiplier is pixel_clk/ref_clk @@ -452,7 +452,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, * is greater than 1000MHz */ pi->dcofreq = phy > 1000 * 100; - pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; + pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; /* Set the reference clock to sysclk reference */ pi->refsel = HDMI_REFSEL_SYSCLK; diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index cb3a2d6753de..403c66241477 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -92,7 +92,7 @@ static int hdmi_pll_init(struct hdmi_ip_data *ip_data) r = hdmi_read_reg(pll_base, PLLCTRL_CFG1); r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ - r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ + r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ hdmi_write_reg(pll_base, PLLCTRL_CFG1, r); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 44f423ff64bd..c7cfdad81242 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -520,6 +520,7 @@ struct omap_dss_device { } dsi; struct { + /* regn is one greater than TRM's REGN value */ u16 regn; u16 regm2; } hdmi; -- cgit 1.4.1 From c90a78ecc2ae3c8341ed6efbfbb7e3e655ee00fe Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 31 Aug 2011 15:32:23 +0300 Subject: OMAP: DSS2: DSI: Add comment about regn regn divider is one greater than the REGN divider in TRM. Add a comment to point this out. Signed-off-by: Tomi Valkeinen --- include/video/omapdss.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/video') diff --git a/include/video/omapdss.h b/include/video/omapdss.h index c7cfdad81242..31b77469c151 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -510,6 +510,7 @@ struct omap_dss_device { } dispc; struct { + /* regn is one greater than TRM's REGN value */ u16 regn; u16 regm; u16 regm_dispc; -- cgit 1.4.1 From 7f6f3c4bf3f0fd4ea82682b5f1a417cbdbf4a27f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 31 Aug 2011 13:39:03 +0300 Subject: OMAP: DSS2: DISPC: Add missing IRQ definitions Add IRQ definitions for missing OMAP4 IRQs: FRAMEDONEWB, FRAMEDONETV, WBBUFFEROVERFLOW. Signed-off-by: Tomi Valkeinen --- include/video/omapdss.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/video') diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 31b77469c151..583c6245194f 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -43,6 +43,9 @@ #define DISPC_IRQ_VSYNC2 (1 << 18) #define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21) #define DISPC_IRQ_FRAMEDONE2 (1 << 22) +#define DISPC_IRQ_FRAMEDONEWB (1 << 23) +#define DISPC_IRQ_FRAMEDONETV (1 << 24) +#define DISPC_IRQ_WBBUFFEROVERFLOW (1 << 25) struct omap_dss_device; struct omap_overlay_manager; -- cgit 1.4.1 From 3d5e0ef746c13f8a26d0150f5dfd4f9b738a5130 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 25 Aug 2011 17:10:41 +0300 Subject: OMAP: DSS2: add read_edid() to omap_dss_driver struct read_edid() can be used to get the EDID information from the display. Signed-off-by: Tomi Valkeinen --- include/video/omapdss.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/video') diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 583c6245194f..33410b499f3a 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -622,6 +622,8 @@ struct omap_dss_driver { int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); u32 (*get_wss)(struct omap_dss_device *dssdev); + + int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); }; int omap_dss_register_driver(struct omap_dss_driver *); -- cgit 1.4.1 From df4769c9c4effa0960ead8d83522407f66e4a82a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 29 Aug 2011 17:26:01 +0300 Subject: OMAP: DSS2: add detect() to omap_dss_driver struct detect() can be used to probe if the display is connected. Signed-off-by: Tomi Valkeinen --- include/video/omapdss.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/video') diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 33410b499f3a..a927eea8e9b9 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -624,6 +624,7 @@ struct omap_dss_driver { u32 (*get_wss)(struct omap_dss_device *dssdev); int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); + bool (*detect)(struct omap_dss_device *dssdev); }; int omap_dss_register_driver(struct omap_dss_driver *); -- cgit 1.4.1 From ba2eac9ed32e4485b2a76e1a0922837d3ffd6149 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 1 Sep 2011 09:17:41 +0300 Subject: OMAP: DSS2: add panel-dvi driver We have currently panel-generic-dpi driver, which is a combined driver for dummy panels and also for DVI output. The aim is to split the panel-generic-dpi into two, one for fixed size dummy panels connected via DPI, and the other (this) for variable resolution output which supports DDC channel (in practice a DVI framer chip connected to DPI output). Original i2c code by: Ricardo Salveti de Araujo Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/Kconfig | 7 + drivers/video/omap2/displays/Makefile | 1 + drivers/video/omap2/displays/panel-dvi.c | 363 +++++++++++++++++++++++++++++++ include/video/omap-panel-dvi.h | 37 ++++ 4 files changed, 408 insertions(+) create mode 100644 drivers/video/omap2/displays/panel-dvi.c create mode 100644 include/video/omap-panel-dvi.h (limited to 'include/video') diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 6ddb401552cd..16e3eab444c4 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI Supports LCD Panel used in TI SDP3430 and EVM boards, OMAP3517 EVM boards and CM-T35. +config PANEL_DVI + tristate "DVI output" + depends on OMAP2_DSS_DPI + help + Driver for external monitors, connected via DVI. The driver uses i2c + to read EDID information from the monitor. + config PANEL_LGPHILIPS_LB035Q02 tristate "LG.Philips LB035Q02 LCD Panel" depends on OMAP2_DSS_DPI && SPI diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index d90f73c8716a..abfda35d82d4 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o +obj-$(CONFIG_PANEL_DVI) += panel-dvi.o obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c new file mode 100644 index 000000000000..03eb14af33e0 --- /dev/null +++ b/drivers/video/omap2/displays/panel-dvi.c @@ -0,0 +1,363 @@ +/* + * DVI output support + * + * Copyright (C) 2011 Texas Instruments Inc + * Author: Tomi Valkeinen + * + * 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 . + */ + +#include +#include +#include