#include <linux/pm_runtime.h>
#include <video/omapdss.h>
+#include <video/mipi_display.h>
#include <plat/clock.h>
#include "dss.h"
DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
-#define DSI_DT_DCS_SHORT_WRITE_0 0x05
-#define DSI_DT_DCS_SHORT_WRITE_1 0x15
-#define DSI_DT_DCS_READ 0x06
-#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
-#define DSI_DT_NULL_PACKET 0x09
-#define DSI_DT_DCS_LONG_WRITE 0x39
-
-#define DSI_DT_RX_ACK_WITH_ERR 0x02
-#define DSI_DT_RX_DCS_LONG_READ 0x1c
-#define DSI_DT_RX_SHORT_READ_1 0x21
-#define DSI_DT_RX_SHORT_READ_2 0x22
-
typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
#define DSI_MAX_NR_ISRS 2
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;
return dsi_pdev_map[module];
}
-static int dsi_get_dsidev_id(struct platform_device *dsidev)
+static inline int dsi_get_dsidev_id(struct platform_device *dsidev)
{
- /* TEMP: Pass 0 as the dsi module index till the time the dsi platform
- * device names aren't changed to the form "omapdss_dsi.0",
- * "omapdss_dsi.1" and so on */
- BUG_ON(dsidev->id != -1);
-
- return 0;
+ return dsidev->id;
}
static inline void dsi_write_reg(struct platform_device *dsidev,
* with DSS_SYS_CLK source also */
cinfo->highfreq = 0;
} else {
- cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
+ cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);
if (cinfo->clkin < 32000000)
cinfo->highfreq = 0;
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);
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);
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,
val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
DSSERR("\trawval %#08x\n", val);
dt = FLD_GET(val, 5, 0);
- if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
u16 err = FLD_GET(val, 23, 8);
dsi_show_rx_ack_with_err(err);
- } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
DSSERR("\tDCS short response, 1 byte: %#x\n",
FLD_GET(val, 23, 8));
- } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
DSSERR("\tDCS short response, 2 byte: %#x\n",
FLD_GET(val, 23, 8));
- } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
DSSERR("\tDCS long response, len %d\n",
FLD_GET(val, 23, 8));
dsi_vc_flush_long_data(dsidev, channel);
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
u8 nullpkg[] = {0, 0, 0, 0};
- return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg,
+ return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, nullpkg,
4, 0);
}
EXPORT_SYMBOL(dsi_vc_send_null);
BUG_ON(len == 0);
if (len == 1) {
- r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0,
- data[0], 0);
+ r = dsi_vc_send_short(dsidev, channel,
+ MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
} else if (len == 2) {
- r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1,
+ r = dsi_vc_send_short(dsidev, channel,
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM,
data[0] | (data[1] << 8), 0);
} else {
/* 0x39 = DCS Long Write */
- r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
+ r = dsi_vc_send_long(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
data, len, 0);
}
if (dsi->debug_read)
DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd);
- r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0);
+ r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
if (r)
goto err;
if (dsi->debug_read)
DSSDBG("\theader: %08x\n", val);
dt = FLD_GET(val, 5, 0);
- if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
u16 err = FLD_GET(val, 23, 8);
dsi_show_rx_ack_with_err(err);
r = -EIO;
goto err;
- } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ } else if (dt == 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);
buf[0] = data;
return 1;
- } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ } else if (dt == 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);
buf[1] = (data >> 8) & 0xff;
return 2;
- } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
int w;
int len = FLD_GET(val, 23, 8);
if (dsi->debug_read)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
- len, 0);
+ return dsi_vc_send_short(dsidev, channel,
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
}
EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
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)
{
l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
- dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
+ dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
packet_len, 0);
if (dsi->te_enabled)
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_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
return 0;
}
* 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->framedone_callback = callback;
+ dsi->framedone_data = data;
- dsi_update_screen_dispc(dssdev, x, y, w, h);
- } else {
- int r;
-
- 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;
}
return r;
}
- dispc_set_lcd_display_type(dssdev->manager->id,
+ dispc_mgr_set_lcd_display_type(dssdev->manager->id,
OMAP_DSS_LCD_DISPLAY_TFT);
- dispc_set_parallel_interface_mode(dssdev->manager->id,
+ dispc_mgr_set_parallel_interface_mode(dssdev->manager->id,
OMAP_DSS_PARALLELMODE_DSI);
- dispc_enable_fifohandcheck(dssdev->manager->id, 1);
+ dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1);
- dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
+ dispc_mgr_set_tft_data_lines(dssdev->manager->id,
+ dssdev->ctrl.pixel_size);
{
struct omap_video_timings timings = {
.vbp = 0,
};
- dispc_set_lcd_timings(dssdev->manager->id, &timings);
+ dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings);
}
return 0;
return r;
}
- r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+ r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r) {
DSSERR("Failed to set dispc clocks\n");
return r;
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);
+ dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+
err1:
dsi_pll_uninit(dsidev, true);
err0:
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);
+ dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+ dsi_cio_uninit(dssdev);
dsi_pll_uninit(dsidev, disconnect_lanes);
}
mutex_lock(&dsi->lock);
+ if (dssdev->manager == NULL) {
+ DSSERR("failed to enable display: no manager\n");
+ r = -ENODEV;
+ goto err_start_dev;
+ }
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
dsi->dss_clk = clk;
- if (cpu_is_omap34xx() || cpu_is_omap3630())
- clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
- else
- clk = clk_get(&dsidev->dev, "sys_clk");
+ clk = clk_get(&dsidev->dev, "sys_clk");
if (IS_ERR(clk)) {
DSSERR("can't get sys_clk\n");
clk_put(dsi->dss_clk);
}
/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int omap_dsihw_probe(struct platform_device *dsidev)
{
struct omap_display_platform_data *dss_plat_data;
struct omap_dss_board_info *board_info;
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);
return r;
}
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static int omap_dsihw_remove(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
static int dsi_runtime_suspend(struct device *dev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
-
- clk_disable(dsi->dss_clk);
-
dispc_runtime_put();
dss_runtime_put();
static int dsi_runtime_resume(struct device *dev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
int r;
r = dss_runtime_get();
if (r)
goto err_get_dispc;
- clk_enable(dsi->dss_clk);
-
return 0;
err_get_dispc:
.runtime_resume = dsi_runtime_resume,
};
-static struct platform_driver omap_dsi1hw_driver = {
- .probe = omap_dsi1hw_probe,
- .remove = omap_dsi1hw_remove,
+static struct platform_driver omap_dsihw_driver = {
+ .probe = omap_dsihw_probe,
+ .remove = omap_dsihw_remove,
.driver = {
- .name = "omapdss_dsi1",
+ .name = "omapdss_dsi",
.owner = THIS_MODULE,
.pm = &dsi_pm_ops,
},
int dsi_init_platform_driver(void)
{
- return platform_driver_register(&omap_dsi1hw_driver);
+ return platform_driver_register(&omap_dsihw_driver);
}
void dsi_uninit_platform_driver(void)
{
- return platform_driver_unregister(&omap_dsi1hw_driver);
+ return platform_driver_unregister(&omap_dsihw_driver);
}