|
@@ -44,6 +44,7 @@
|
|
|
#include <linux/of_graph.h>
|
|
|
#include <linux/of_platform.h>
|
|
|
#include <linux/component.h>
|
|
|
+#include <linux/sys_soc.h>
|
|
|
|
|
|
#include <video/mipi_display.h>
|
|
|
|
|
@@ -312,10 +313,20 @@ struct dsi_module_id_data {
|
|
|
int id;
|
|
|
};
|
|
|
|
|
|
+enum dsi_quirks {
|
|
|
+ DSI_QUIRK_PLL_PWR_BUG = (1 << 0), /* DSI-PLL power command 0x3 is not working */
|
|
|
+ DSI_QUIRK_DCS_CMD_CONFIG_VC = (1 << 1),
|
|
|
+ DSI_QUIRK_VC_OCP_WIDTH = (1 << 2),
|
|
|
+ DSI_QUIRK_REVERSE_TXCLKESC = (1 << 3),
|
|
|
+ DSI_QUIRK_GNQ = (1 << 4),
|
|
|
+ DSI_QUIRK_PHY_DCC = (1 << 5),
|
|
|
+};
|
|
|
+
|
|
|
struct dsi_of_data {
|
|
|
enum dsi_model model;
|
|
|
const struct dss_pll_hw *pll_hw;
|
|
|
const struct dsi_module_id_data *modules;
|
|
|
+ enum dsi_quirks quirks;
|
|
|
};
|
|
|
|
|
|
struct dsi_data {
|
|
@@ -418,8 +429,6 @@ struct dsi_packet_sent_handler_data {
|
|
|
struct completion *completion;
|
|
|
};
|
|
|
|
|
|
-static const struct of_device_id dsi_of_match[];
|
|
|
-
|
|
|
#ifdef DSI_PERF_MEASURE
|
|
|
static bool dsi_perf;
|
|
|
module_param(dsi_perf, bool, 0644);
|
|
@@ -1202,6 +1211,7 @@ static int dsi_regulator_init(struct platform_device *dsidev)
|
|
|
|
|
|
static void _dsi_print_reset_status(struct platform_device *dsidev)
|
|
|
{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
u32 l;
|
|
|
int b0, b1, b2;
|
|
|
|
|
@@ -1210,7 +1220,7 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
|
|
|
* I/O. */
|
|
|
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
|
|
|
|
|
|
- if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
|
|
|
+ if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC) {
|
|
|
b0 = 28;
|
|
|
b1 = 27;
|
|
|
b2 = 26;
|
|
@@ -1365,11 +1375,12 @@ enum dsi_pll_power_state {
|
|
|
static int dsi_pll_power(struct platform_device *dsidev,
|
|
|
enum dsi_pll_power_state state)
|
|
|
{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
int t = 0;
|
|
|
|
|
|
/* DSI-PLL power command 0x3 is not working */
|
|
|
- if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
|
|
|
- state == DSI_PLL_POWER_ON_DIV)
|
|
|
+ if ((dsi->data->quirks & DSI_QUIRK_PLL_PWR_BUG) &&
|
|
|
+ state == DSI_PLL_POWER_ON_DIV)
|
|
|
state = DSI_PLL_POWER_ON_ALL;
|
|
|
|
|
|
/* PLL_PWR_CMD */
|
|
@@ -1789,13 +1800,14 @@ static int dsi_cio_power(struct platform_device *dsidev,
|
|
|
|
|
|
static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
|
|
|
{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
int val;
|
|
|
|
|
|
/* line buffer on OMAP3 is 1024 x 24bits */
|
|
|
/* XXX: for some reason using full buffer size causes
|
|
|
* considerable TX slowdown with update sizes that fill the
|
|
|
* whole buffer */
|
|
|
- if (!dss_has_feature(FEAT_DSI_GNQ))
|
|
|
+ if (!(dsi->data->quirks & DSI_QUIRK_GNQ))
|
|
|
return 1023 * 3;
|
|
|
|
|
|
val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */
|
|
@@ -1888,6 +1900,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
|
|
|
|
|
|
static void dsi_cio_timings(struct platform_device *dsidev)
|
|
|
{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
u32 r;
|
|
|
u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
|
|
|
u32 tlpx_half, tclk_trail, tclk_zero;
|
|
@@ -1950,7 +1963,7 @@ static void dsi_cio_timings(struct platform_device *dsidev)
|
|
|
r = FLD_MOD(r, tclk_trail, 15, 8);
|
|
|
r = FLD_MOD(r, tclk_zero, 7, 0);
|
|
|
|
|
|
- if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
|
|
|
+ if (dsi->data->quirks & DSI_QUIRK_PHY_DCC) {
|
|
|
r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
|
|
|
r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
|
|
|
r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
|
|
@@ -2022,7 +2035,7 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
|
|
|
static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
|
|
|
const u8 *offsets;
|
|
|
|
|
|
- if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
|
|
|
+ if (dsi->data->quirks & DSI_QUIRK_REVERSE_TXCLKESC)
|
|
|
offsets = offsets_old;
|
|
|
else
|
|
|
offsets = offsets_new;
|
|
@@ -2513,7 +2526,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
|
|
|
r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
|
|
|
r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
|
|
|
r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
|
|
|
- if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
|
|
|
+ if (dsi->data->quirks & DSI_QUIRK_VC_OCP_WIDTH)
|
|
|
r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */
|
|
|
|
|
|
r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
|
|
@@ -2548,7 +2561,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
|
|
|
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
|
|
|
|
|
|
/* DCS_CMD_ENABLE */
|
|
|
- if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
|
|
|
+ if (dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC) {
|
|
|
bool enable = source == DSI_VC_SOURCE_VP;
|
|
|
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
|
|
|
}
|
|
@@ -3681,7 +3694,7 @@ static int dsi_proto_config(struct platform_device *dsidev)
|
|
|
r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
|
|
|
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)) {
|
|
|
+ if (!(dsi->data->quirks & DSI_QUIRK_DCS_CMD_CONFIG_VC)) {
|
|
|
r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
|
|
|
/* DCS_CMD_CODE, 1=start, 0=continue */
|
|
|
r = FLD_MOD(r, 0, 25, 25);
|
|
@@ -5315,9 +5328,66 @@ static int dsi_init_pll_data(struct platform_device *dsidev)
|
|
|
}
|
|
|
|
|
|
/* DSI1 HW IP initialisation */
|
|
|
+static const struct dsi_of_data dsi_of_data_omap34xx = {
|
|
|
+ .model = DSI_MODEL_OMAP3,
|
|
|
+ .pll_hw = &dss_omap3_dsi_pll_hw,
|
|
|
+ .modules = (const struct dsi_module_id_data[]) {
|
|
|
+ { .address = 0x4804fc00, .id = 0, },
|
|
|
+ { },
|
|
|
+ },
|
|
|
+ .quirks = DSI_QUIRK_REVERSE_TXCLKESC,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct dsi_of_data dsi_of_data_omap36xx = {
|
|
|
+ .model = DSI_MODEL_OMAP3,
|
|
|
+ .pll_hw = &dss_omap3_dsi_pll_hw,
|
|
|
+ .modules = (const struct dsi_module_id_data[]) {
|
|
|
+ { .address = 0x4804fc00, .id = 0, },
|
|
|
+ { },
|
|
|
+ },
|
|
|
+ .quirks = DSI_QUIRK_PLL_PWR_BUG,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct dsi_of_data dsi_of_data_omap4 = {
|
|
|
+ .model = DSI_MODEL_OMAP4,
|
|
|
+ .pll_hw = &dss_omap4_dsi_pll_hw,
|
|
|
+ .modules = (const struct dsi_module_id_data[]) {
|
|
|
+ { .address = 0x58004000, .id = 0, },
|
|
|
+ { .address = 0x58005000, .id = 1, },
|
|
|
+ { },
|
|
|
+ },
|
|
|
+ .quirks = DSI_QUIRK_DCS_CMD_CONFIG_VC | DSI_QUIRK_VC_OCP_WIDTH
|
|
|
+ | DSI_QUIRK_GNQ,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct dsi_of_data dsi_of_data_omap5 = {
|
|
|
+ .model = DSI_MODEL_OMAP5,
|
|
|
+ .pll_hw = &dss_omap5_dsi_pll_hw,
|
|
|
+ .modules = (const struct dsi_module_id_data[]) {
|
|
|
+ { .address = 0x58004000, .id = 0, },
|
|
|
+ { .address = 0x58009000, .id = 1, },
|
|
|
+ { },
|
|
|
+ },
|
|
|
+ .quirks = DSI_QUIRK_DCS_CMD_CONFIG_VC | DSI_QUIRK_VC_OCP_WIDTH
|
|
|
+ | DSI_QUIRK_GNQ | DSI_QUIRK_PHY_DCC,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct of_device_id dsi_of_match[] = {
|
|
|
+ { .compatible = "ti,omap3-dsi", .data = &dsi_of_data_omap36xx, },
|
|
|
+ { .compatible = "ti,omap4-dsi", .data = &dsi_of_data_omap4, },
|
|
|
+ { .compatible = "ti,omap5-dsi", .data = &dsi_of_data_omap5, },
|
|
|
+ {},
|
|
|
+};
|
|
|
+
|
|
|
+static const struct soc_device_attribute dsi_soc_devices[] = {
|
|
|
+ { .machine = "OMAP3[45]*", .data = &dsi_of_data_omap34xx },
|
|
|
+ { .machine = "AM35*", .data = &dsi_of_data_omap34xx },
|
|
|
+ { /* sentinel */ }
|
|
|
+};
|
|
|
static int dsi_bind(struct device *dev, struct device *master, void *data)
|
|
|
{
|
|
|
struct platform_device *dsidev = to_platform_device(dev);
|
|
|
+ const struct soc_device_attribute *soc;
|
|
|
const struct dsi_module_id_data *d;
|
|
|
u32 rev;
|
|
|
int r, i;
|
|
@@ -5381,7 +5451,12 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
- dsi->data = of_match_node(dsi_of_match, dsidev->dev.of_node)->data;
|
|
|
+ soc = soc_device_match(dsi_soc_devices);
|
|
|
+ if (soc)
|
|
|
+ dsi->data = soc->data;
|
|
|
+ else
|
|
|
+ dsi->data = of_match_node(dsi_of_match, dev->of_node)->data;
|
|
|
+
|
|
|
d = dsi->data->modules;
|
|
|
while (d->address != 0 && d->address != dsi_mem->start)
|
|
|
d++;
|
|
@@ -5433,7 +5508,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
|
|
|
|
|
|
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
|
|
|
* of data to 3 by default */
|
|
|
- if (dss_has_feature(FEAT_DSI_GNQ))
|
|
|
+ if (dsi->data->quirks & DSI_QUIRK_GNQ)
|
|
|
/* NB_DATA_LANES */
|
|
|
dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
|
|
|
else
|
|
@@ -5553,42 +5628,6 @@ static const struct dev_pm_ops dsi_pm_ops = {
|
|
|
.runtime_resume = dsi_runtime_resume,
|
|
|
};
|
|
|
|
|
|
-static const struct dsi_of_data dsi_of_data_omap3 = {
|
|
|
- .model = DSI_MODEL_OMAP3,
|
|
|
- .pll_hw = &dss_omap3_dsi_pll_hw,
|
|
|
- .modules = (const struct dsi_module_id_data[]) {
|
|
|
- { .address = 0x4804fc00, .id = 0, },
|
|
|
- { },
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
-static const struct dsi_of_data dsi_of_data_omap4 = {
|
|
|
- .model = DSI_MODEL_OMAP4,
|
|
|
- .pll_hw = &dss_omap4_dsi_pll_hw,
|
|
|
- .modules = (const struct dsi_module_id_data[]) {
|
|
|
- { .address = 0x58004000, .id = 0, },
|
|
|
- { .address = 0x58005000, .id = 1, },
|
|
|
- { },
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
-static const struct dsi_of_data dsi_of_data_omap5 = {
|
|
|
- .model = DSI_MODEL_OMAP5,
|
|
|
- .pll_hw = &dss_omap5_dsi_pll_hw,
|
|
|
- .modules = (const struct dsi_module_id_data[]) {
|
|
|
- { .address = 0x58004000, .id = 0, },
|
|
|
- { .address = 0x58009000, .id = 1, },
|
|
|
- { },
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
-static const struct of_device_id dsi_of_match[] = {
|
|
|
- { .compatible = "ti,omap3-dsi", .data = &dsi_of_data_omap3, },
|
|
|
- { .compatible = "ti,omap4-dsi", .data = &dsi_of_data_omap4, },
|
|
|
- { .compatible = "ti,omap5-dsi", .data = &dsi_of_data_omap5, },
|
|
|
- {},
|
|
|
-};
|
|
|
-
|
|
|
static struct platform_driver omap_dsihw_driver = {
|
|
|
.probe = dsi_probe,
|
|
|
.remove = dsi_remove,
|