|
@@ -38,12 +38,11 @@
|
|
#include <plat/clock.h>
|
|
#include <plat/clock.h>
|
|
|
|
|
|
#include "dss.h"
|
|
#include "dss.h"
|
|
|
|
+#include "dss_features.h"
|
|
|
|
|
|
/*#define VERBOSE_IRQ*/
|
|
/*#define VERBOSE_IRQ*/
|
|
#define DSI_CATCH_MISSING_TE
|
|
#define DSI_CATCH_MISSING_TE
|
|
|
|
|
|
-#define DSI_BASE 0x4804FC00
|
|
|
|
-
|
|
|
|
struct dsi_reg { u16 idx; };
|
|
struct dsi_reg { u16 idx; };
|
|
|
|
|
|
#define DSI_REG(idx) ((const struct dsi_reg) { idx })
|
|
#define DSI_REG(idx) ((const struct dsi_reg) { idx })
|
|
@@ -186,13 +185,15 @@ struct dsi_reg { u16 idx; };
|
|
#define DSI_DT_RX_SHORT_READ_1 0x21
|
|
#define DSI_DT_RX_SHORT_READ_1 0x21
|
|
#define DSI_DT_RX_SHORT_READ_2 0x22
|
|
#define DSI_DT_RX_SHORT_READ_2 0x22
|
|
|
|
|
|
-#define FINT_MAX 2100000
|
|
|
|
-#define FINT_MIN 750000
|
|
|
|
-#define REGN_MAX (1 << 7)
|
|
|
|
-#define REGM_MAX ((1 << 11) - 1)
|
|
|
|
-#define REGM3_MAX (1 << 4)
|
|
|
|
-#define REGM4_MAX (1 << 4)
|
|
|
|
-#define LP_DIV_MAX ((1 << 13) - 1)
|
|
|
|
|
|
+typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
|
|
|
|
+
|
|
|
|
+#define DSI_MAX_NR_ISRS 2
|
|
|
|
+
|
|
|
|
+struct dsi_isr_data {
|
|
|
|
+ omap_dsi_isr_t isr;
|
|
|
|
+ void *arg;
|
|
|
|
+ u32 mask;
|
|
|
|
+};
|
|
|
|
|
|
enum fifo_size {
|
|
enum fifo_size {
|
|
DSI_FIFO_SIZE_0 = 0,
|
|
DSI_FIFO_SIZE_0 = 0,
|
|
@@ -220,9 +221,17 @@ struct dsi_irq_stats {
|
|
unsigned cio_irqs[32];
|
|
unsigned cio_irqs[32];
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+struct dsi_isr_tables {
|
|
|
|
+ struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
|
|
|
|
+ struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
|
|
|
|
+ struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
|
|
|
|
+};
|
|
|
|
+
|
|
static struct
|
|
static struct
|
|
{
|
|
{
|
|
|
|
+ struct platform_device *pdev;
|
|
void __iomem *base;
|
|
void __iomem *base;
|
|
|
|
+ int irq;
|
|
|
|
|
|
struct dsi_clock_info current_cinfo;
|
|
struct dsi_clock_info current_cinfo;
|
|
|
|
|
|
@@ -232,6 +241,7 @@ static struct
|
|
enum dsi_vc_mode mode;
|
|
enum dsi_vc_mode mode;
|
|
struct omap_dss_device *dssdev;
|
|
struct omap_dss_device *dssdev;
|
|
enum fifo_size fifo_size;
|
|
enum fifo_size fifo_size;
|
|
|
|
+ int vc_id;
|
|
} vc[4];
|
|
} vc[4];
|
|
|
|
|
|
struct mutex lock;
|
|
struct mutex lock;
|
|
@@ -239,8 +249,10 @@ static struct
|
|
|
|
|
|
unsigned pll_locked;
|
|
unsigned pll_locked;
|
|
|
|
|
|
- struct completion bta_completion;
|
|
|
|
- void (*bta_callback)(void);
|
|
|
|
|
|
+ spinlock_t irq_lock;
|
|
|
|
+ struct dsi_isr_tables isr_tables;
|
|
|
|
+ /* space for a copy used by the interrupt handler */
|
|
|
|
+ struct dsi_isr_tables isr_tables_copy;
|
|
|
|
|
|
int update_channel;
|
|
int update_channel;
|
|
struct dsi_update_region update_region;
|
|
struct dsi_update_region update_region;
|
|
@@ -275,6 +287,11 @@ static struct
|
|
spinlock_t irq_stats_lock;
|
|
spinlock_t irq_stats_lock;
|
|
struct dsi_irq_stats irq_stats;
|
|
struct dsi_irq_stats irq_stats;
|
|
#endif
|
|
#endif
|
|
|
|
+ /* DSI PLL Parameter Ranges */
|
|
|
|
+ unsigned long regm_max, regn_max;
|
|
|
|
+ unsigned long regm_dispc_max, regm_dsi_max;
|
|
|
|
+ unsigned long fint_min, fint_max;
|
|
|
|
+ unsigned long lpdiv_max;
|
|
} dsi;
|
|
} dsi;
|
|
|
|
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
@@ -318,6 +335,11 @@ static bool dsi_bus_is_locked(void)
|
|
return dsi.bus_lock.count == 0;
|
|
return dsi.bus_lock.count == 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void dsi_completion_handler(void *data, u32 mask)
|
|
|
|
+{
|
|
|
|
+ complete((struct completion *)data);
|
|
|
|
+}
|
|
|
|
+
|
|
static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
|
|
static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
|
|
int value)
|
|
int value)
|
|
{
|
|
{
|
|
@@ -387,6 +409,9 @@ static void dsi_perf_show(const char *name)
|
|
|
|
|
|
static void print_irq_status(u32 status)
|
|
static void print_irq_status(u32 status)
|
|
{
|
|
{
|
|
|
|
+ if (status == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
#ifndef VERBOSE_IRQ
|
|
#ifndef VERBOSE_IRQ
|
|
if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
|
|
if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
|
|
return;
|
|
return;
|
|
@@ -422,6 +447,9 @@ static void print_irq_status(u32 status)
|
|
|
|
|
|
static void print_irq_status_vc(int channel, u32 status)
|
|
static void print_irq_status_vc(int channel, u32 status)
|
|
{
|
|
{
|
|
|
|
+ if (status == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
#ifndef VERBOSE_IRQ
|
|
#ifndef VERBOSE_IRQ
|
|
if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
|
|
if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
|
|
return;
|
|
return;
|
|
@@ -448,6 +476,9 @@ static void print_irq_status_vc(int channel, u32 status)
|
|
|
|
|
|
static void print_irq_status_cio(u32 status)
|
|
static void print_irq_status_cio(u32 status)
|
|
{
|
|
{
|
|
|
|
+ if (status == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
|
|
printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
|
|
|
|
|
|
#define PIS(x) \
|
|
#define PIS(x) \
|
|
@@ -478,22 +509,33 @@ static void print_irq_status_cio(u32 status)
|
|
printk("\n");
|
|
printk("\n");
|
|
}
|
|
}
|
|
|
|
|
|
-static int debug_irq;
|
|
|
|
-
|
|
|
|
-/* called from dss */
|
|
|
|
-void dsi_irq_handler(void)
|
|
|
|
|
|
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
+static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
|
|
{
|
|
{
|
|
- u32 irqstatus, vcstatus, ciostatus;
|
|
|
|
int i;
|
|
int i;
|
|
|
|
|
|
- irqstatus = dsi_read_reg(DSI_IRQSTATUS);
|
|
|
|
-
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
spin_lock(&dsi.irq_stats_lock);
|
|
spin_lock(&dsi.irq_stats_lock);
|
|
|
|
+
|
|
dsi.irq_stats.irq_count++;
|
|
dsi.irq_stats.irq_count++;
|
|
dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
|
|
dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 4; ++i)
|
|
|
|
+ dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]);
|
|
|
|
+
|
|
|
|
+ dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
|
|
|
|
+
|
|
|
|
+ spin_unlock(&dsi.irq_stats_lock);
|
|
|
|
+}
|
|
|
|
+#else
|
|
|
|
+#define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+static int debug_irq;
|
|
|
|
+
|
|
|
|
+static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+
|
|
if (irqstatus & DSI_IRQ_ERROR_MASK) {
|
|
if (irqstatus & DSI_IRQ_ERROR_MASK) {
|
|
DSSERR("DSI error, irqstatus %x\n", irqstatus);
|
|
DSSERR("DSI error, irqstatus %x\n", irqstatus);
|
|
print_irq_status(irqstatus);
|
|
print_irq_status(irqstatus);
|
|
@@ -504,37 +546,88 @@ void dsi_irq_handler(void)
|
|
print_irq_status(irqstatus);
|
|
print_irq_status(irqstatus);
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef DSI_CATCH_MISSING_TE
|
|
|
|
- if (irqstatus & DSI_IRQ_TE_TRIGGER)
|
|
|
|
- del_timer(&dsi.te_timer);
|
|
|
|
-#endif
|
|
|
|
|
|
+ for (i = 0; i < 4; ++i) {
|
|
|
|
+ if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
|
|
|
|
+ DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
|
|
|
|
+ i, vcstatus[i]);
|
|
|
|
+ print_irq_status_vc(i, vcstatus[i]);
|
|
|
|
+ } else if (debug_irq) {
|
|
|
|
+ print_irq_status_vc(i, vcstatus[i]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
|
|
|
|
+ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
|
|
|
|
+ print_irq_status_cio(ciostatus);
|
|
|
|
+ } else if (debug_irq) {
|
|
|
|
+ print_irq_status_cio(ciostatus);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void dsi_call_isrs(struct dsi_isr_data *isr_array,
|
|
|
|
+ unsigned isr_array_size, u32 irqstatus)
|
|
|
|
+{
|
|
|
|
+ struct dsi_isr_data *isr_data;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < isr_array_size; i++) {
|
|
|
|
+ isr_data = &isr_array[i];
|
|
|
|
+ if (isr_data->isr && isr_data->mask & irqstatus)
|
|
|
|
+ isr_data->isr(isr_data->arg, irqstatus);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
|
|
|
|
+ u32 irqstatus, u32 *vcstatus, u32 ciostatus)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ dsi_call_isrs(isr_tables->isr_table,
|
|
|
|
+ ARRAY_SIZE(isr_tables->isr_table),
|
|
|
|
+ irqstatus);
|
|
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
for (i = 0; i < 4; ++i) {
|
|
- if ((irqstatus & (1<<i)) == 0)
|
|
|
|
|
|
+ if (vcstatus[i] == 0)
|
|
continue;
|
|
continue;
|
|
|
|
+ dsi_call_isrs(isr_tables->isr_table_vc[i],
|
|
|
|
+ ARRAY_SIZE(isr_tables->isr_table_vc[i]),
|
|
|
|
+ vcstatus[i]);
|
|
|
|
+ }
|
|
|
|
|
|
- vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
|
|
|
|
|
|
+ if (ciostatus != 0)
|
|
|
|
+ dsi_call_isrs(isr_tables->isr_table_cio,
|
|
|
|
+ ARRAY_SIZE(isr_tables->isr_table_cio),
|
|
|
|
+ ciostatus);
|
|
|
|
+}
|
|
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
|
|
|
|
-#endif
|
|
|
|
|
|
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
|
|
|
|
+{
|
|
|
|
+ u32 irqstatus, vcstatus[4], ciostatus;
|
|
|
|
+ int i;
|
|
|
|
|
|
- if (vcstatus & DSI_VC_IRQ_BTA) {
|
|
|
|
- complete(&dsi.bta_completion);
|
|
|
|
|
|
+ spin_lock(&dsi.irq_lock);
|
|
|
|
|
|
- if (dsi.bta_callback)
|
|
|
|
- dsi.bta_callback();
|
|
|
|
- }
|
|
|
|
|
|
+ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
|
|
|
|
|
|
- if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
|
|
|
|
- DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
|
|
|
|
- i, vcstatus);
|
|
|
|
- print_irq_status_vc(i, vcstatus);
|
|
|
|
- } else if (debug_irq) {
|
|
|
|
- print_irq_status_vc(i, vcstatus);
|
|
|
|
|
|
+ /* IRQ is not for us */
|
|
|
|
+ if (!irqstatus) {
|
|
|
|
+ spin_unlock(&dsi.irq_lock);
|
|
|
|
+ return IRQ_NONE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
|
|
|
|
+ /* flush posted write */
|
|
|
|
+ dsi_read_reg(DSI_IRQSTATUS);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 4; ++i) {
|
|
|
|
+ if ((irqstatus & (1 << i)) == 0) {
|
|
|
|
+ vcstatus[i] = 0;
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
|
|
- dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
|
|
|
|
|
|
+ vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i));
|
|
|
|
+
|
|
|
|
+ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]);
|
|
/* flush posted write */
|
|
/* flush posted write */
|
|
dsi_read_reg(DSI_VC_IRQSTATUS(i));
|
|
dsi_read_reg(DSI_VC_IRQSTATUS(i));
|
|
}
|
|
}
|
|
@@ -542,117 +635,307 @@ void dsi_irq_handler(void)
|
|
if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
|
|
if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
|
|
ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
|
|
ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
|
|
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
|
|
dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
|
|
/* flush posted write */
|
|
/* flush posted write */
|
|
dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
|
|
dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
|
|
|
|
+ } else {
|
|
|
|
+ ciostatus = 0;
|
|
|
|
+ }
|
|
|
|
|
|
- if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
|
|
|
|
- DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
|
|
|
|
- print_irq_status_cio(ciostatus);
|
|
|
|
- } else if (debug_irq) {
|
|
|
|
- print_irq_status_cio(ciostatus);
|
|
|
|
- }
|
|
|
|
|
|
+#ifdef DSI_CATCH_MISSING_TE
|
|
|
|
+ if (irqstatus & DSI_IRQ_TE_TRIGGER)
|
|
|
|
+ del_timer(&dsi.te_timer);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ /* make a copy and unlock, so that isrs can unregister
|
|
|
|
+ * themselves */
|
|
|
|
+ memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables));
|
|
|
|
+
|
|
|
|
+ spin_unlock(&dsi.irq_lock);
|
|
|
|
+
|
|
|
|
+ dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus);
|
|
|
|
+
|
|
|
|
+ dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus);
|
|
|
|
+
|
|
|
|
+ dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus);
|
|
|
|
+
|
|
|
|
+ return IRQ_HANDLED;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* dsi.irq_lock has to be locked by the caller */
|
|
|
|
+static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array,
|
|
|
|
+ unsigned isr_array_size, u32 default_mask,
|
|
|
|
+ const struct dsi_reg enable_reg,
|
|
|
|
+ const struct dsi_reg status_reg)
|
|
|
|
+{
|
|
|
|
+ struct dsi_isr_data *isr_data;
|
|
|
|
+ u32 mask;
|
|
|
|
+ u32 old_mask;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ mask = default_mask;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < isr_array_size; i++) {
|
|
|
|
+ isr_data = &isr_array[i];
|
|
|
|
+
|
|
|
|
+ if (isr_data->isr == NULL)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ mask |= isr_data->mask;
|
|
}
|
|
}
|
|
|
|
|
|
- dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
|
|
|
|
- /* flush posted write */
|
|
|
|
- dsi_read_reg(DSI_IRQSTATUS);
|
|
|
|
|
|
+ old_mask = dsi_read_reg(enable_reg);
|
|
|
|
+ /* clear the irqstatus for newly enabled irqs */
|
|
|
|
+ dsi_write_reg(status_reg, (mask ^ old_mask) & mask);
|
|
|
|
+ dsi_write_reg(enable_reg, mask);
|
|
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- spin_unlock(&dsi.irq_stats_lock);
|
|
|
|
|
|
+ /* flush posted writes */
|
|
|
|
+ dsi_read_reg(enable_reg);
|
|
|
|
+ dsi_read_reg(status_reg);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* dsi.irq_lock has to be locked by the caller */
|
|
|
|
+static void _omap_dsi_set_irqs(void)
|
|
|
|
+{
|
|
|
|
+ u32 mask = DSI_IRQ_ERROR_MASK;
|
|
|
|
+#ifdef DSI_CATCH_MISSING_TE
|
|
|
|
+ mask |= DSI_IRQ_TE_TRIGGER;
|
|
#endif
|
|
#endif
|
|
|
|
+ _omap_dsi_configure_irqs(dsi.isr_tables.isr_table,
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table), mask,
|
|
|
|
+ DSI_IRQENABLE, DSI_IRQSTATUS);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* dsi.irq_lock has to be locked by the caller */
|
|
|
|
+static void _omap_dsi_set_irqs_vc(int vc)
|
|
|
|
+{
|
|
|
|
+ _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc],
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]),
|
|
|
|
+ DSI_VC_IRQ_ERROR_MASK,
|
|
|
|
+ DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* dsi.irq_lock has to be locked by the caller */
|
|
|
|
+static void _omap_dsi_set_irqs_cio(void)
|
|
|
|
+{
|
|
|
|
+ _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio,
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table_cio),
|
|
|
|
+ DSI_CIO_IRQ_ERROR_MASK,
|
|
|
|
+ DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
|
|
|
|
+}
|
|
|
|
|
|
static void _dsi_initialize_irq(void)
|
|
static void _dsi_initialize_irq(void)
|
|
{
|
|
{
|
|
- u32 l;
|
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int vc;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables));
|
|
|
|
+
|
|
|
|
+ _omap_dsi_set_irqs();
|
|
|
|
+ for (vc = 0; vc < 4; ++vc)
|
|
|
|
+ _omap_dsi_set_irqs_vc(vc);
|
|
|
|
+ _omap_dsi_set_irqs_cio();
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
|
|
|
|
+ struct dsi_isr_data *isr_array, unsigned isr_array_size)
|
|
|
|
+{
|
|
|
|
+ struct dsi_isr_data *isr_data;
|
|
|
|
+ int free_idx;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
- /* disable all interrupts */
|
|
|
|
- dsi_write_reg(DSI_IRQENABLE, 0);
|
|
|
|
- for (i = 0; i < 4; ++i)
|
|
|
|
- dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
|
|
|
|
- dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
|
|
|
|
|
|
+ BUG_ON(isr == NULL);
|
|
|
|
|
|
- /* clear interrupt status */
|
|
|
|
- l = dsi_read_reg(DSI_IRQSTATUS);
|
|
|
|
- dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
|
|
|
|
|
|
+ /* check for duplicate entry and find a free slot */
|
|
|
|
+ free_idx = -1;
|
|
|
|
+ for (i = 0; i < isr_array_size; i++) {
|
|
|
|
+ isr_data = &isr_array[i];
|
|
|
|
|
|
- for (i = 0; i < 4; ++i) {
|
|
|
|
- l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
|
|
|
|
- dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
|
|
|
|
|
|
+ if (isr_data->isr == isr && isr_data->arg == arg &&
|
|
|
|
+ isr_data->mask == mask) {
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (isr_data->isr == NULL && free_idx == -1)
|
|
|
|
+ free_idx = i;
|
|
}
|
|
}
|
|
|
|
|
|
- l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
|
|
|
|
- dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
|
|
|
|
|
|
+ if (free_idx == -1)
|
|
|
|
+ return -EBUSY;
|
|
|
|
|
|
- /* enable error irqs */
|
|
|
|
- l = DSI_IRQ_ERROR_MASK;
|
|
|
|
-#ifdef DSI_CATCH_MISSING_TE
|
|
|
|
- l |= DSI_IRQ_TE_TRIGGER;
|
|
|
|
-#endif
|
|
|
|
- dsi_write_reg(DSI_IRQENABLE, l);
|
|
|
|
|
|
+ isr_data = &isr_array[free_idx];
|
|
|
|
+ isr_data->isr = isr;
|
|
|
|
+ isr_data->arg = arg;
|
|
|
|
+ isr_data->mask = mask;
|
|
|
|
|
|
- l = DSI_VC_IRQ_ERROR_MASK;
|
|
|
|
- for (i = 0; i < 4; ++i)
|
|
|
|
- dsi_write_reg(DSI_VC_IRQENABLE(i), l);
|
|
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
|
|
|
|
+ struct dsi_isr_data *isr_array, unsigned isr_array_size)
|
|
|
|
+{
|
|
|
|
+ struct dsi_isr_data *isr_data;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < isr_array_size; i++) {
|
|
|
|
+ isr_data = &isr_array[i];
|
|
|
|
+ if (isr_data->isr != isr || isr_data->arg != arg ||
|
|
|
|
+ isr_data->mask != mask)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ isr_data->isr = NULL;
|
|
|
|
+ isr_data->arg = NULL;
|
|
|
|
+ isr_data->mask = 0;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- l = DSI_CIO_IRQ_ERROR_MASK;
|
|
|
|
- dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
-static u32 dsi_get_errors(void)
|
|
|
|
|
|
+static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
- u32 e;
|
|
|
|
- spin_lock_irqsave(&dsi.errors_lock, flags);
|
|
|
|
- e = dsi.errors;
|
|
|
|
- dsi.errors = 0;
|
|
|
|
- spin_unlock_irqrestore(&dsi.errors_lock, flags);
|
|
|
|
- return e;
|
|
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table,
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table));
|
|
|
|
+
|
|
|
|
+ if (r == 0)
|
|
|
|
+ _omap_dsi_set_irqs();
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ return r;
|
|
}
|
|
}
|
|
|
|
|
|
-static void dsi_vc_enable_bta_irq(int channel)
|
|
|
|
|
|
+static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
|
|
{
|
|
{
|
|
- u32 l;
|
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table,
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table));
|
|
|
|
+
|
|
|
|
+ if (r == 0)
|
|
|
|
+ _omap_dsi_set_irqs();
|
|
|
|
|
|
- dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
|
|
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
|
|
- l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
|
|
|
|
- l |= DSI_VC_IRQ_BTA;
|
|
|
|
- dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
|
|
|
|
|
|
+ return r;
|
|
}
|
|
}
|
|
|
|
|
|
-static void dsi_vc_disable_bta_irq(int channel)
|
|
|
|
|
|
+static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
|
|
|
|
+ u32 mask)
|
|
{
|
|
{
|
|
- u32 l;
|
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ r = _dsi_register_isr(isr, arg, mask,
|
|
|
|
+ dsi.isr_tables.isr_table_vc[channel],
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
|
|
|
|
+
|
|
|
|
+ if (r == 0)
|
|
|
|
+ _omap_dsi_set_irqs_vc(channel);
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
|
|
|
|
+ u32 mask)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ r = _dsi_unregister_isr(isr, arg, mask,
|
|
|
|
+ dsi.isr_tables.isr_table_vc[channel],
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
|
|
|
|
+
|
|
|
|
+ if (r == 0)
|
|
|
|
+ _omap_dsi_set_irqs_vc(channel);
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
|
|
|
|
+
|
|
|
|
+ if (r == 0)
|
|
|
|
+ _omap_dsi_set_irqs_cio();
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ int r;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&dsi.irq_lock, flags);
|
|
|
|
+
|
|
|
|
+ r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
|
|
|
|
+ ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
|
|
|
|
+
|
|
|
|
+ if (r == 0)
|
|
|
|
+ _omap_dsi_set_irqs_cio();
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&dsi.irq_lock, flags);
|
|
|
|
|
|
- l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
|
|
|
|
- l &= ~DSI_VC_IRQ_BTA;
|
|
|
|
- dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
|
|
|
|
|
|
+ return r;
|
|
}
|
|
}
|
|
|
|
|
|
-/* DSI func clock. this could also be DSI2_PLL_FCLK */
|
|
|
|
|
|
+static u32 dsi_get_errors(void)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ u32 e;
|
|
|
|
+ spin_lock_irqsave(&dsi.errors_lock, flags);
|
|
|
|
+ e = dsi.errors;
|
|
|
|
+ dsi.errors = 0;
|
|
|
|
+ spin_unlock_irqrestore(&dsi.errors_lock, flags);
|
|
|
|
+ return e;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
|
|
static inline void enable_clocks(bool enable)
|
|
static inline void enable_clocks(bool enable)
|
|
{
|
|
{
|
|
if (enable)
|
|
if (enable)
|
|
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
|
|
|
|
|
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
|
|
else
|
|
else
|
|
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
|
|
|
|
|
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
|
|
}
|
|
}
|
|
|
|
|
|
/* source clock for DSI PLL. this could also be PCLKFREE */
|
|
/* source clock for DSI PLL. this could also be PCLKFREE */
|
|
static inline void dsi_enable_pll_clock(bool enable)
|
|
static inline void dsi_enable_pll_clock(bool enable)
|
|
{
|
|
{
|
|
if (enable)
|
|
if (enable)
|
|
- dss_clk_enable(DSS_CLK_FCK2);
|
|
|
|
|
|
+ dss_clk_enable(DSS_CLK_SYSCK);
|
|
else
|
|
else
|
|
- dss_clk_disable(DSS_CLK_FCK2);
|
|
|
|
|
|
+ dss_clk_disable(DSS_CLK_SYSCK);
|
|
|
|
|
|
if (enable && dsi.pll_locked) {
|
|
if (enable && dsi.pll_locked) {
|
|
if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
|
|
if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
|
|
@@ -707,14 +990,14 @@ static inline int dsi_if_enable(bool enable)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-unsigned long dsi_get_dsi1_pll_rate(void)
|
|
|
|
|
|
+unsigned long dsi_get_pll_hsdiv_dispc_rate(void)
|
|
{
|
|
{
|
|
- return dsi.current_cinfo.dsi1_pll_fclk;
|
|
|
|
|
|
+ return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long dsi_get_dsi2_pll_rate(void)
|
|
|
|
|
|
+static unsigned long dsi_get_pll_hsdiv_dsi_rate(void)
|
|
{
|
|
{
|
|
- return dsi.current_cinfo.dsi2_pll_fclk;
|
|
|
|
|
|
+ return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk;
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned long dsi_get_txbyteclkhs(void)
|
|
static unsigned long dsi_get_txbyteclkhs(void)
|
|
@@ -726,12 +1009,12 @@ static unsigned long dsi_fclk_rate(void)
|
|
{
|
|
{
|
|
unsigned long r;
|
|
unsigned long r;
|
|
|
|
|
|
- if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) {
|
|
|
|
- /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
|
|
|
|
- r = dss_clk_get_rate(DSS_CLK_FCK1);
|
|
|
|
|
|
+ if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) {
|
|
|
|
+ /* DSI FCLK source is DSS_CLK_FCK */
|
|
|
|
+ r = dss_clk_get_rate(DSS_CLK_FCK);
|
|
} else {
|
|
} else {
|
|
- /* DSI FCLK source is DSI2_PLL_FCLK */
|
|
|
|
- r = dsi_get_dsi2_pll_rate();
|
|
|
|
|
|
+ /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
|
|
|
|
+ r = dsi_get_pll_hsdiv_dsi_rate();
|
|
}
|
|
}
|
|
|
|
|
|
return r;
|
|
return r;
|
|
@@ -745,7 +1028,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
|
|
|
|
|
|
lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
|
|
lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
|
|
|
|
|
|
- if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX)
|
|
|
|
|
|
+ if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
dsi_fclk = dsi_fclk_rate();
|
|
dsi_fclk = dsi_fclk_rate();
|
|
@@ -795,22 +1078,22 @@ static int dsi_pll_power(enum dsi_pll_power_state state)
|
|
static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
|
|
static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
|
|
struct dsi_clock_info *cinfo)
|
|
struct dsi_clock_info *cinfo)
|
|
{
|
|
{
|
|
- if (cinfo->regn == 0 || cinfo->regn > REGN_MAX)
|
|
|
|
|
|
+ if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (cinfo->regm == 0 || cinfo->regm > REGM_MAX)
|
|
|
|
|
|
+ if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (cinfo->regm3 > REGM3_MAX)
|
|
|
|
|
|
+ if (cinfo->regm_dispc > dsi.regm_dispc_max)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (cinfo->regm4 > REGM4_MAX)
|
|
|
|
|
|
+ if (cinfo->regm_dsi > dsi.regm_dsi_max)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (cinfo->use_dss2_fck) {
|
|
|
|
- cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2);
|
|
|
|
|
|
+ if (cinfo->use_sys_clk) {
|
|
|
|
+ cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
|
|
/* XXX it is unclear if highfreq should be used
|
|
/* XXX it is unclear if highfreq should be used
|
|
- * with DSS2_FCK source also */
|
|
|
|
|
|
+ * with DSS_SYS_CLK source also */
|
|
cinfo->highfreq = 0;
|
|
cinfo->highfreq = 0;
|
|
} else {
|
|
} else {
|
|
cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
|
|
cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
|
|
@@ -823,7 +1106,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
|
|
|
|
|
|
cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
|
|
cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
|
|
|
|
|
|
- if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN)
|
|
|
|
|
|
+ if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
|
|
cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
|
|
@@ -831,15 +1114,17 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
|
|
if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
|
|
if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (cinfo->regm3 > 0)
|
|
|
|
- cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3;
|
|
|
|
|
|
+ if (cinfo->regm_dispc > 0)
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dispc_clk =
|
|
|
|
+ cinfo->clkin4ddr / cinfo->regm_dispc;
|
|
else
|
|
else
|
|
- cinfo->dsi1_pll_fclk = 0;
|
|
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dispc_clk = 0;
|
|
|
|
|
|
- if (cinfo->regm4 > 0)
|
|
|
|
- cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4;
|
|
|
|
|
|
+ if (cinfo->regm_dsi > 0)
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dsi_clk =
|
|
|
|
+ cinfo->clkin4ddr / cinfo->regm_dsi;
|
|
else
|
|
else
|
|
- cinfo->dsi2_pll_fclk = 0;
|
|
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dsi_clk = 0;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -852,23 +1137,25 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
|
|
struct dispc_clock_info best_dispc;
|
|
struct dispc_clock_info best_dispc;
|
|
int min_fck_per_pck;
|
|
int min_fck_per_pck;
|
|
int match = 0;
|
|
int match = 0;
|
|
- unsigned long dss_clk_fck2;
|
|
|
|
|
|
+ unsigned long dss_sys_clk, max_dss_fck;
|
|
|
|
+
|
|
|
|
+ dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
|
|
|
|
|
|
- dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
|
|
|
|
|
|
+ max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
|
|
|
|
|
if (req_pck == dsi.cache_req_pck &&
|
|
if (req_pck == dsi.cache_req_pck &&
|
|
- dsi.cache_cinfo.clkin == dss_clk_fck2) {
|
|
|
|
|
|
+ dsi.cache_cinfo.clkin == dss_sys_clk) {
|
|
DSSDBG("DSI clock info found from cache\n");
|
|
DSSDBG("DSI clock info found from cache\n");
|
|
*dsi_cinfo = dsi.cache_cinfo;
|
|
*dsi_cinfo = dsi.cache_cinfo;
|
|
- dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk,
|
|
|
|
- dispc_cinfo);
|
|
|
|
|
|
+ dispc_find_clk_divs(is_tft, req_pck,
|
|
|
|
+ dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
|
min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
|
|
|
|
|
if (min_fck_per_pck &&
|
|
if (min_fck_per_pck &&
|
|
- req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
|
|
|
|
|
|
+ req_pck * min_fck_per_pck > max_dss_fck) {
|
|
DSSERR("Requested pixel clock not possible with the current "
|
|
DSSERR("Requested pixel clock not possible with the current "
|
|
"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
|
|
"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
|
|
"the constraint off.\n");
|
|
"the constraint off.\n");
|
|
@@ -882,24 +1169,24 @@ retry:
|
|
memset(&best_dispc, 0, sizeof(best_dispc));
|
|
memset(&best_dispc, 0, sizeof(best_dispc));
|
|
|
|
|
|
memset(&cur, 0, sizeof(cur));
|
|
memset(&cur, 0, sizeof(cur));
|
|
- cur.clkin = dss_clk_fck2;
|
|
|
|
- cur.use_dss2_fck = 1;
|
|
|
|
|
|
+ cur.clkin = dss_sys_clk;
|
|
|
|
+ cur.use_sys_clk = 1;
|
|
cur.highfreq = 0;
|
|
cur.highfreq = 0;
|
|
|
|
|
|
/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
|
|
/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
|
|
/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
|
|
/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
|
|
/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
|
|
/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
|
|
- for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
|
|
|
|
|
|
+ for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) {
|
|
if (cur.highfreq == 0)
|
|
if (cur.highfreq == 0)
|
|
cur.fint = cur.clkin / cur.regn;
|
|
cur.fint = cur.clkin / cur.regn;
|
|
else
|
|
else
|
|
cur.fint = cur.clkin / (2 * cur.regn);
|
|
cur.fint = cur.clkin / (2 * cur.regn);
|
|
|
|
|
|
- if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
|
|
|
|
|
|
+ if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
|
|
/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
|
|
- for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
|
|
|
|
|
|
+ for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) {
|
|
unsigned long a, b;
|
|
unsigned long a, b;
|
|
|
|
|
|
a = 2 * cur.regm * (cur.clkin/1000);
|
|
a = 2 * cur.regm * (cur.clkin/1000);
|
|
@@ -909,30 +1196,32 @@ retry:
|
|
if (cur.clkin4ddr > 1800 * 1000 * 1000)
|
|
if (cur.clkin4ddr > 1800 * 1000 * 1000)
|
|
break;
|
|
break;
|
|
|
|
|
|
- /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
|
|
|
|
- for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
|
|
|
|
- ++cur.regm3) {
|
|
|
|
|
|
+ /* dsi_pll_hsdiv_dispc_clk(MHz) =
|
|
|
|
+ * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */
|
|
|
|
+ for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max;
|
|
|
|
+ ++cur.regm_dispc) {
|
|
struct dispc_clock_info cur_dispc;
|
|
struct dispc_clock_info cur_dispc;
|
|
- cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3;
|
|
|
|
|
|
+ cur.dsi_pll_hsdiv_dispc_clk =
|
|
|
|
+ cur.clkin4ddr / cur.regm_dispc;
|
|
|
|
|
|
/* this will narrow down the search a bit,
|
|
/* this will narrow down the search a bit,
|
|
* but still give pixclocks below what was
|
|
* but still give pixclocks below what was
|
|
* requested */
|
|
* requested */
|
|
- if (cur.dsi1_pll_fclk < req_pck)
|
|
|
|
|
|
+ if (cur.dsi_pll_hsdiv_dispc_clk < req_pck)
|
|
break;
|
|
break;
|
|
|
|
|
|
- if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
|
|
|
|
|
|
+ if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if (min_fck_per_pck &&
|
|
if (min_fck_per_pck &&
|
|
- cur.dsi1_pll_fclk <
|
|
|
|
|
|
+ cur.dsi_pll_hsdiv_dispc_clk <
|
|
req_pck * min_fck_per_pck)
|
|
req_pck * min_fck_per_pck)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
match = 1;
|
|
match = 1;
|
|
|
|
|
|
dispc_find_clk_divs(is_tft, req_pck,
|
|
dispc_find_clk_divs(is_tft, req_pck,
|
|
- cur.dsi1_pll_fclk,
|
|
|
|
|
|
+ cur.dsi_pll_hsdiv_dispc_clk,
|
|
&cur_dispc);
|
|
&cur_dispc);
|
|
|
|
|
|
if (abs(cur_dispc.pck - req_pck) <
|
|
if (abs(cur_dispc.pck - req_pck) <
|
|
@@ -961,9 +1250,9 @@ found:
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- /* DSI2_PLL_FCLK (regm4) is not used */
|
|
|
|
- best.regm4 = 0;
|
|
|
|
- best.dsi2_pll_fclk = 0;
|
|
|
|
|
|
+ /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
|
|
|
|
+ best.regm_dsi = 0;
|
|
|
|
+ best.dsi_pll_hsdiv_dsi_clk = 0;
|
|
|
|
|
|
if (dsi_cinfo)
|
|
if (dsi_cinfo)
|
|
*dsi_cinfo = best;
|
|
*dsi_cinfo = best;
|
|
@@ -982,23 +1271,27 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
|
|
int r = 0;
|
|
int r = 0;
|
|
u32 l;
|
|
u32 l;
|
|
int f;
|
|
int f;
|
|
|
|
+ u8 regn_start, regn_end, regm_start, regm_end;
|
|
|
|
+ u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
|
|
|
|
|
|
DSSDBGF();
|
|
DSSDBGF();
|
|
|
|
|
|
dsi.current_cinfo.fint = cinfo->fint;
|
|
dsi.current_cinfo.fint = cinfo->fint;
|
|
dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
|
|
dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
|
|
- dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
|
|
|
|
- dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
|
|
|
|
|
|
+ dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk =
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dispc_clk;
|
|
|
|
+ dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk =
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dsi_clk;
|
|
|
|
|
|
dsi.current_cinfo.regn = cinfo->regn;
|
|
dsi.current_cinfo.regn = cinfo->regn;
|
|
dsi.current_cinfo.regm = cinfo->regm;
|
|
dsi.current_cinfo.regm = cinfo->regm;
|
|
- dsi.current_cinfo.regm3 = cinfo->regm3;
|
|
|
|
- dsi.current_cinfo.regm4 = cinfo->regm4;
|
|
|
|
|
|
+ dsi.current_cinfo.regm_dispc = cinfo->regm_dispc;
|
|
|
|
+ dsi.current_cinfo.regm_dsi = cinfo->regm_dsi;
|
|
|
|
|
|
DSSDBG("DSI Fint %ld\n", cinfo->fint);
|
|
DSSDBG("DSI Fint %ld\n", cinfo->fint);
|
|
|
|
|
|
DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
|
|
DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
|
|
- cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
|
|
|
|
|
|
+ cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree",
|
|
cinfo->clkin,
|
|
cinfo->clkin,
|
|
cinfo->highfreq);
|
|
cinfo->highfreq);
|
|
|
|
|
|
@@ -1015,24 +1308,39 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
|
|
|
|
|
|
DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
|
|
DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
|
|
|
|
|
|
- DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
|
|
|
|
- cinfo->regm3, cinfo->dsi1_pll_fclk);
|
|
|
|
- DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
|
|
|
|
- cinfo->regm4, cinfo->dsi2_pll_fclk);
|
|
|
|
|
|
+ DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
|
|
|
|
+ dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
|
|
|
|
+ dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dispc_clk);
|
|
|
|
+ DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
|
|
|
|
+ dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
|
|
|
|
+ dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dsi_clk);
|
|
|
|
+
|
|
|
|
+ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end);
|
|
|
|
+ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end);
|
|
|
|
+ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start,
|
|
|
|
+ ®m_dispc_end);
|
|
|
|
+ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start,
|
|
|
|
+ ®m_dsi_end);
|
|
|
|
|
|
REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
|
|
REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
|
|
|
|
|
|
l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
|
|
l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
|
|
l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
|
|
l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
|
|
- l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
|
|
|
|
- l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
|
|
|
|
- l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0,
|
|
|
|
- 22, 19); /* DSI_CLOCK_DIV */
|
|
|
|
- l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0,
|
|
|
|
- 26, 23); /* DSIPROTO_CLOCK_DIV */
|
|
|
|
|
|
+ /* DSI_PLL_REGN */
|
|
|
|
+ l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
|
|
|
|
+ /* DSI_PLL_REGM */
|
|
|
|
+ l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
|
|
|
|
+ /* DSI_CLOCK_DIV */
|
|
|
|
+ l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
|
|
|
|
+ regm_dispc_start, regm_dispc_end);
|
|
|
|
+ /* DSIPROTO_CLOCK_DIV */
|
|
|
|
+ l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
|
|
|
|
+ regm_dsi_start, regm_dsi_end);
|
|
dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
|
|
dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
|
|
|
|
|
|
- BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000);
|
|
|
|
|
|
+ BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max);
|
|
if (cinfo->fint < 1000000)
|
|
if (cinfo->fint < 1000000)
|
|
f = 0x3;
|
|
f = 0x3;
|
|
else if (cinfo->fint < 1250000)
|
|
else if (cinfo->fint < 1250000)
|
|
@@ -1046,7 +1354,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
|
|
|
|
|
|
l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
|
|
l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
|
|
l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
|
|
l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
|
|
- l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1,
|
|
|
|
|
|
+ l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
|
|
11, 11); /* DSI_PLL_CLKSEL */
|
|
11, 11); /* DSI_PLL_CLKSEL */
|
|
l = FLD_MOD(l, cinfo->highfreq,
|
|
l = FLD_MOD(l, cinfo->highfreq,
|
|
12, 12); /* DSI_PLL_HIGHFREQ */
|
|
12, 12); /* DSI_PLL_HIGHFREQ */
|
|
@@ -1101,6 +1409,26 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
|
|
|
|
|
|
DSSDBG("PLL init\n");
|
|
DSSDBG("PLL init\n");
|
|
|
|
|
|
|
|
+#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
|
|
|
|
+ /*
|
|
|
|
+ * HACK: this is just a quick hack to get the USE_DSI_PLL
|
|
|
|
+ * option working. USE_DSI_PLL is itself a big hack, and
|
|
|
|
+ * should be removed.
|
|
|
|
+ */
|
|
|
|
+ if (dsi.vdds_dsi_reg == NULL) {
|
|
|
|
+ struct regulator *vdds_dsi;
|
|
|
|
+
|
|
|
|
+ vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi");
|
|
|
|
+
|
|
|
|
+ if (IS_ERR(vdds_dsi)) {
|
|
|
|
+ DSSERR("can't get VDDS_DSI regulator\n");
|
|
|
|
+ return PTR_ERR(vdds_dsi);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dsi.vdds_dsi_reg = vdds_dsi;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
enable_clocks(1);
|
|
enable_clocks(1);
|
|
dsi_enable_pll_clock(1);
|
|
dsi_enable_pll_clock(1);
|
|
|
|
|
|
@@ -1162,6 +1490,10 @@ void dsi_dump_clocks(struct seq_file *s)
|
|
{
|
|
{
|
|
int clksel;
|
|
int clksel;
|
|
struct dsi_clock_info *cinfo = &dsi.current_cinfo;
|
|
struct dsi_clock_info *cinfo = &dsi.current_cinfo;
|
|
|
|
+ enum dss_clk_source dispc_clk_src, dsi_clk_src;
|
|
|
|
+
|
|
|
|
+ dispc_clk_src = dss_get_dispc_clk_source();
|
|
|
|
+ dsi_clk_src = dss_get_dsi_clk_source();
|
|
|
|
|
|
enable_clocks(1);
|
|
enable_clocks(1);
|
|
|
|
|
|
@@ -1171,30 +1503,34 @@ void dsi_dump_clocks(struct seq_file *s)
|
|
|
|
|
|
seq_printf(s, "dsi pll source = %s\n",
|
|
seq_printf(s, "dsi pll source = %s\n",
|
|
clksel == 0 ?
|
|
clksel == 0 ?
|
|
- "dss2_alwon_fclk" : "pclkfree");
|
|
|
|
|
|
+ "dss_sys_clk" : "pclkfree");
|
|
|
|
|
|
seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
|
|
seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
|
|
|
|
|
|
seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
|
|
seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
|
|
cinfo->clkin4ddr, cinfo->regm);
|
|
cinfo->clkin4ddr, cinfo->regm);
|
|
|
|
|
|
- seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n",
|
|
|
|
- cinfo->dsi1_pll_fclk,
|
|
|
|
- cinfo->regm3,
|
|
|
|
- dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
|
|
|
|
|
|
+ seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n",
|
|
|
|
+ dss_get_generic_clk_source_name(dispc_clk_src),
|
|
|
|
+ dss_feat_get_clk_source_name(dispc_clk_src),
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dispc_clk,
|
|
|
|
+ cinfo->regm_dispc,
|
|
|
|
+ dispc_clk_src == DSS_CLK_SRC_FCK ?
|
|
"off" : "on");
|
|
"off" : "on");
|
|
|
|
|
|
- seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n",
|
|
|
|
- cinfo->dsi2_pll_fclk,
|
|
|
|
- cinfo->regm4,
|
|
|
|
- dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
|
|
|
|
|
|
+ seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
|
|
|
|
+ dss_get_generic_clk_source_name(dsi_clk_src),
|
|
|
|
+ dss_feat_get_clk_source_name(dsi_clk_src),
|
|
|
|
+ cinfo->dsi_pll_hsdiv_dsi_clk,
|
|
|
|
+ cinfo->regm_dsi,
|
|
|
|
+ dsi_clk_src == DSS_CLK_SRC_FCK ?
|
|
"off" : "on");
|
|
"off" : "on");
|
|
|
|
|
|
seq_printf(s, "- DSI -\n");
|
|
seq_printf(s, "- DSI -\n");
|
|
|
|
|
|
- seq_printf(s, "dsi fclk source = %s\n",
|
|
|
|
- dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
|
|
|
|
- "dss1_alwon_fclk" : "dsi2_pll_fclk");
|
|
|
|
|
|
+ seq_printf(s, "dsi fclk source = %s (%s)\n",
|
|
|
|
+ dss_get_generic_clk_source_name(dsi_clk_src),
|
|
|
|
+ dss_feat_get_clk_source_name(dsi_clk_src));
|
|
|
|
|
|
seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate());
|
|
seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate());
|
|
|
|
|
|
@@ -1306,7 +1642,7 @@ void dsi_dump_regs(struct seq_file *s)
|
|
{
|
|
{
|
|
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
|
|
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
|
|
|
|
|
|
- dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
|
|
|
|
|
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
|
|
|
|
|
|
DUMPREG(DSI_REVISION);
|
|
DUMPREG(DSI_REVISION);
|
|
DUMPREG(DSI_SYSCONFIG);
|
|
DUMPREG(DSI_SYSCONFIG);
|
|
@@ -1378,7 +1714,7 @@ void dsi_dump_regs(struct seq_file *s)
|
|
DUMPREG(DSI_PLL_CONFIGURATION1);
|
|
DUMPREG(DSI_PLL_CONFIGURATION1);
|
|
DUMPREG(DSI_PLL_CONFIGURATION2);
|
|
DUMPREG(DSI_PLL_CONFIGURATION2);
|
|
|
|
|
|
- dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
|
|
|
|
|
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
|
|
#undef DUMPREG
|
|
#undef DUMPREG
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1622,20 +1958,6 @@ static int _dsi_reset(void)
|
|
return _dsi_wait_reset();
|
|
return _dsi_wait_reset();
|
|
}
|
|
}
|
|
|
|
|
|
-static void dsi_reset_tx_fifo(int channel)
|
|
|
|
-{
|
|
|
|
- u32 mask;
|
|
|
|
- u32 l;
|
|
|
|
-
|
|
|
|
- /* set fifosize of the channel to 0, then return the old size */
|
|
|
|
- l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE);
|
|
|
|
-
|
|
|
|
- mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4);
|
|
|
|
- dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask);
|
|
|
|
-
|
|
|
|
- dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
|
|
static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
|
|
enum fifo_size size3, enum fifo_size size4)
|
|
enum fifo_size size3, enum fifo_size size4)
|
|
{
|
|
{
|
|
@@ -1753,8 +2075,6 @@ static void dsi_vc_initial_config(int channel)
|
|
r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
|
|
r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
|
|
|
|
|
|
dsi_write_reg(DSI_VC_CTRL(channel), r);
|
|
dsi_write_reg(DSI_VC_CTRL(channel), r);
|
|
-
|
|
|
|
- dsi.vc[channel].mode = DSI_VC_MODE_L4;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int dsi_vc_config_l4(int channel)
|
|
static int dsi_vc_config_l4(int channel)
|
|
@@ -1922,33 +2242,44 @@ static int dsi_vc_send_bta(int channel)
|
|
|
|
|
|
int dsi_vc_send_bta_sync(int channel)
|
|
int dsi_vc_send_bta_sync(int channel)
|
|
{
|
|
{
|
|
|
|
+ DECLARE_COMPLETION_ONSTACK(completion);
|
|
int r = 0;
|
|
int r = 0;
|
|
u32 err;
|
|
u32 err;
|
|
|
|
|
|
- INIT_COMPLETION(dsi.bta_completion);
|
|
|
|
|
|
+ r = dsi_register_isr_vc(channel, dsi_completion_handler,
|
|
|
|
+ &completion, DSI_VC_IRQ_BTA);
|
|
|
|
+ if (r)
|
|
|
|
+ goto err0;
|
|
|
|
|
|
- dsi_vc_enable_bta_irq(channel);
|
|
|
|
|
|
+ r = dsi_register_isr(dsi_completion_handler, &completion,
|
|
|
|
+ DSI_IRQ_ERROR_MASK);
|
|
|
|
+ if (r)
|
|
|
|
+ goto err1;
|
|
|
|
|
|
r = dsi_vc_send_bta(channel);
|
|
r = dsi_vc_send_bta(channel);
|
|
if (r)
|
|
if (r)
|
|
- goto err;
|
|
|
|
|
|
+ goto err2;
|
|
|
|
|
|
- if (wait_for_completion_timeout(&dsi.bta_completion,
|
|
|
|
|
|
+ if (wait_for_completion_timeout(&completion,
|
|
msecs_to_jiffies(500)) == 0) {
|
|
msecs_to_jiffies(500)) == 0) {
|
|
DSSERR("Failed to receive BTA\n");
|
|
DSSERR("Failed to receive BTA\n");
|
|
r = -EIO;
|
|
r = -EIO;
|
|
- goto err;
|
|
|
|
|
|
+ goto err2;
|
|
}
|
|
}
|
|
|
|
|
|
err = dsi_get_errors();
|
|
err = dsi_get_errors();
|
|
if (err) {
|
|
if (err) {
|
|
DSSERR("Error while sending BTA: %x\n", err);
|
|
DSSERR("Error while sending BTA: %x\n", err);
|
|
r = -EIO;
|
|
r = -EIO;
|
|
- goto err;
|
|
|
|
|
|
+ goto err2;
|
|
}
|
|
}
|
|
-err:
|
|
|
|
- dsi_vc_disable_bta_irq(channel);
|
|
|
|
-
|
|
|
|
|
|
+err2:
|
|
|
|
+ dsi_unregister_isr(dsi_completion_handler, &completion,
|
|
|
|
+ DSI_IRQ_ERROR_MASK);
|
|
|
|
+err1:
|
|
|
|
+ dsi_unregister_isr_vc(channel, dsi_completion_handler,
|
|
|
|
+ &completion, DSI_VC_IRQ_BTA);
|
|
|
|
+err0:
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(dsi_vc_send_bta_sync);
|
|
EXPORT_SYMBOL(dsi_vc_send_bta_sync);
|
|
@@ -1961,7 +2292,7 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type,
|
|
|
|
|
|
WARN_ON(!dsi_bus_is_locked());
|
|
WARN_ON(!dsi_bus_is_locked());
|
|
|
|
|
|
- data_id = data_type | channel << 6;
|
|
|
|
|
|
+ data_id = data_type | dsi.vc[channel].vc_id << 6;
|
|
|
|
|
|
val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
|
|
val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
|
|
FLD_VAL(ecc, 31, 24);
|
|
FLD_VAL(ecc, 31, 24);
|
|
@@ -2064,7 +2395,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- data_id = data_type | channel << 6;
|
|
|
|
|
|
+ data_id = data_type | dsi.vc[channel].vc_id << 6;
|
|
|
|
|
|
r = (data_id << 0) | (data << 8) | (ecc << 24);
|
|
r = (data_id << 0) | (data << 8) | (ecc << 24);
|
|
|
|
|
|
@@ -2762,19 +3093,20 @@ static void dsi_te_timeout(unsigned long arg)
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+static void dsi_framedone_bta_callback(void *data, u32 mask);
|
|
|
|
+
|
|
static void dsi_handle_framedone(int error)
|
|
static void dsi_handle_framedone(int error)
|
|
{
|
|
{
|
|
const int channel = dsi.update_channel;
|
|
const int channel = dsi.update_channel;
|
|
|
|
|
|
- cancel_delayed_work(&dsi.framedone_timeout_work);
|
|
|
|
|
|
+ dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
|
|
|
|
+ NULL, DSI_VC_IRQ_BTA);
|
|
|
|
|
|
- dsi_vc_disable_bta_irq(channel);
|
|
|
|
|
|
+ cancel_delayed_work(&dsi.framedone_timeout_work);
|
|
|
|
|
|
/* SIDLEMODE back to smart-idle */
|
|
/* SIDLEMODE back to smart-idle */
|
|
dispc_enable_sidle();
|
|
dispc_enable_sidle();
|
|
|
|
|
|
- dsi.bta_callback = NULL;
|
|
|
|
-
|
|
|
|
if (dsi.te_enabled) {
|
|
if (dsi.te_enabled) {
|
|
/* enable LP_RX_TO again after the TE */
|
|
/* enable LP_RX_TO again after the TE */
|
|
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
|
|
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
|
|
@@ -2808,7 +3140,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
|
|
dsi_handle_framedone(-ETIMEDOUT);
|
|
dsi_handle_framedone(-ETIMEDOUT);
|
|
}
|
|
}
|
|
|
|
|
|
-static void dsi_framedone_bta_callback(void)
|
|
|
|
|
|
+static void dsi_framedone_bta_callback(void *data, u32 mask)
|
|
{
|
|
{
|
|
dsi_handle_framedone(0);
|
|
dsi_handle_framedone(0);
|
|
|
|
|
|
@@ -2848,15 +3180,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
|
|
* asynchronously.
|
|
* asynchronously.
|
|
* */
|
|
* */
|
|
|
|
|
|
- dsi.bta_callback = dsi_framedone_bta_callback;
|
|
|
|
-
|
|
|
|
- barrier();
|
|
|
|
-
|
|
|
|
- dsi_vc_enable_bta_irq(channel);
|
|
|
|
|
|
+ r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
|
|
|
|
+ NULL, DSI_VC_IRQ_BTA);
|
|
|
|
+ if (r) {
|
|
|
|
+ DSSERR("Failed to register BTA ISR\n");
|
|
|
|
+ dsi_handle_framedone(-EIO);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
r = dsi_vc_send_bta(channel);
|
|
r = dsi_vc_send_bta(channel);
|
|
if (r) {
|
|
if (r) {
|
|
DSSERR("BTA after framedone failed\n");
|
|
DSSERR("BTA after framedone failed\n");
|
|
|
|
+ dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
|
|
|
|
+ NULL, DSI_VC_IRQ_BTA);
|
|
dsi_handle_framedone(-EIO);
|
|
dsi_handle_framedone(-EIO);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2984,12 +3320,12 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
|
|
struct dsi_clock_info cinfo;
|
|
struct dsi_clock_info cinfo;
|
|
int r;
|
|
int r;
|
|
|
|
|
|
- /* we always use DSS2_FCK as input clock */
|
|
|
|
- cinfo.use_dss2_fck = true;
|
|
|
|
|
|
+ /* we always use DSS_CLK_SYSCK as input clock */
|
|
|
|
+ cinfo.use_sys_clk = true;
|
|
cinfo.regn = dssdev->phy.dsi.div.regn;
|
|
cinfo.regn = dssdev->phy.dsi.div.regn;
|
|
cinfo.regm = dssdev->phy.dsi.div.regm;
|
|
cinfo.regm = dssdev->phy.dsi.div.regm;
|
|
- cinfo.regm3 = dssdev->phy.dsi.div.regm3;
|
|
|
|
- cinfo.regm4 = dssdev->phy.dsi.div.regm4;
|
|
|
|
|
|
+ cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc;
|
|
|
|
+ cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi;
|
|
r = dsi_calc_clock_rates(dssdev, &cinfo);
|
|
r = dsi_calc_clock_rates(dssdev, &cinfo);
|
|
if (r) {
|
|
if (r) {
|
|
DSSERR("Failed to calc dsi clocks\n");
|
|
DSSERR("Failed to calc dsi clocks\n");
|
|
@@ -3011,7 +3347,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
|
|
int r;
|
|
int r;
|
|
unsigned long long fck;
|
|
unsigned long long fck;
|
|
|
|
|
|
- fck = dsi_get_dsi1_pll_rate();
|
|
|
|
|
|
+ fck = dsi_get_pll_hsdiv_dispc_rate();
|
|
|
|
|
|
dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
|
|
dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
|
|
dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
|
|
dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
|
|
@@ -3045,8 +3381,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
|
if (r)
|
|
if (r)
|
|
goto err1;
|
|
goto err1;
|
|
|
|
|
|
- dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
|
|
|
|
- dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK);
|
|
|
|
|
|
+ dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
|
|
|
|
+ dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI);
|
|
|
|
|
|
DSSDBG("PLL OK\n");
|
|
DSSDBG("PLL OK\n");
|
|
|
|
|
|
@@ -3082,8 +3418,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
|
err3:
|
|
err3:
|
|
dsi_complexio_uninit();
|
|
dsi_complexio_uninit();
|
|
err2:
|
|
err2:
|
|
- dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
|
|
|
- dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
|
|
|
|
|
+ dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
|
|
|
|
+ dss_select_dsi_clk_source(DSS_CLK_SRC_FCK);
|
|
err1:
|
|
err1:
|
|
dsi_pll_uninit();
|
|
dsi_pll_uninit();
|
|
err0:
|
|
err0:
|
|
@@ -3099,8 +3435,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
|
|
dsi_vc_enable(2, 0);
|
|
dsi_vc_enable(2, 0);
|
|
dsi_vc_enable(3, 0);
|
|
dsi_vc_enable(3, 0);
|
|
|
|
|
|
- dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
|
|
|
- dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
|
|
|
|
|
+ dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
|
|
|
|
+ dss_select_dsi_clk_source(DSS_CLK_SRC_FCK);
|
|
dsi_complexio_uninit();
|
|
dsi_complexio_uninit();
|
|
dsi_pll_uninit();
|
|
dsi_pll_uninit();
|
|
}
|
|
}
|
|
@@ -3220,29 +3556,107 @@ int dsi_init_display(struct omap_dss_device *dssdev)
|
|
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
|
|
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
|
|
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
|
|
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
|
|
|
|
|
|
- dsi.vc[0].dssdev = dssdev;
|
|
|
|
- dsi.vc[1].dssdev = dssdev;
|
|
|
|
|
|
+ if (dsi.vdds_dsi_reg == NULL) {
|
|
|
|
+ struct regulator *vdds_dsi;
|
|
|
|
+
|
|
|
|
+ vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi");
|
|
|
|
+
|
|
|
|
+ if (IS_ERR(vdds_dsi)) {
|
|
|
|
+ DSSERR("can't get VDDS_DSI regulator\n");
|
|
|
|
+ return PTR_ERR(vdds_dsi);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dsi.vdds_dsi_reg = vdds_dsi;
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-void dsi_wait_dsi1_pll_active(void)
|
|
|
|
|
|
+int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) {
|
|
|
|
+ if (!dsi.vc[i].dssdev) {
|
|
|
|
+ dsi.vc[i].dssdev = dssdev;
|
|
|
|
+ *channel = i;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DSSERR("cannot get VC for display %s", dssdev->name);
|
|
|
|
+ return -ENOSPC;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(omap_dsi_request_vc);
|
|
|
|
+
|
|
|
|
+int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
|
|
|
|
+{
|
|
|
|
+ if (vc_id < 0 || vc_id > 3) {
|
|
|
|
+ DSSERR("VC ID out of range\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (channel < 0 || channel > 3) {
|
|
|
|
+ DSSERR("Virtual Channel out of range\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dsi.vc[channel].dssdev != dssdev) {
|
|
|
|
+ DSSERR("Virtual Channel not allocated to display %s\n",
|
|
|
|
+ dssdev->name);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dsi.vc[channel].vc_id = vc_id;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(omap_dsi_set_vc_id);
|
|
|
|
+
|
|
|
|
+void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel)
|
|
|
|
+{
|
|
|
|
+ if ((channel >= 0 && channel <= 3) &&
|
|
|
|
+ dsi.vc[channel].dssdev == dssdev) {
|
|
|
|
+ dsi.vc[channel].dssdev = NULL;
|
|
|
|
+ dsi.vc[channel].vc_id = 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(omap_dsi_release_vc);
|
|
|
|
+
|
|
|
|
+void dsi_wait_pll_hsdiv_dispc_active(void)
|
|
{
|
|
{
|
|
if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
|
|
if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
|
|
- DSSERR("DSI1 PLL clock not active\n");
|
|
|
|
|
|
+ DSSERR("%s (%s) not active\n",
|
|
|
|
+ dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
|
|
|
|
+ dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
|
|
}
|
|
}
|
|
|
|
|
|
-void dsi_wait_dsi2_pll_active(void)
|
|
|
|
|
|
+void dsi_wait_pll_hsdiv_dsi_active(void)
|
|
{
|
|
{
|
|
if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
|
|
if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
|
|
- DSSERR("DSI2 PLL clock not active\n");
|
|
|
|
|
|
+ DSSERR("%s (%s) not active\n",
|
|
|
|
+ dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
|
|
|
|
+ dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void dsi_calc_clock_param_ranges(void)
|
|
|
|
+{
|
|
|
|
+ dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
|
|
|
|
+ dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
|
|
|
|
+ dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
|
|
|
|
+ dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
|
|
|
|
+ dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
|
|
|
|
+ dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
|
|
|
|
+ dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
|
|
}
|
|
}
|
|
|
|
|
|
-int dsi_init(struct platform_device *pdev)
|
|
|
|
|
|
+static int dsi_init(struct platform_device *pdev)
|
|
{
|
|
{
|
|
u32 rev;
|
|
u32 rev;
|
|
- int r;
|
|
|
|
|
|
+ int r, i;
|
|
|
|
+ struct resource *dsi_mem;
|
|
|
|
|
|
|
|
+ spin_lock_init(&dsi.irq_lock);
|
|
spin_lock_init(&dsi.errors_lock);
|
|
spin_lock_init(&dsi.errors_lock);
|
|
dsi.errors = 0;
|
|
dsi.errors = 0;
|
|
|
|
|
|
@@ -3251,8 +3665,6 @@ int dsi_init(struct platform_device *pdev)
|
|
dsi.irq_stats.last_reset = jiffies;
|
|
dsi.irq_stats.last_reset = jiffies;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- init_completion(&dsi.bta_completion);
|
|
|
|
-
|
|
|
|
mutex_init(&dsi.lock);
|
|
mutex_init(&dsi.lock);
|
|
sema_init(&dsi.bus_lock, 1);
|
|
sema_init(&dsi.bus_lock, 1);
|
|
|
|
|
|
@@ -3268,24 +3680,45 @@ int dsi_init(struct platform_device *pdev)
|
|
dsi.te_timer.function = dsi_te_timeout;
|
|
dsi.te_timer.function = dsi_te_timeout;
|
|
dsi.te_timer.data = 0;
|
|
dsi.te_timer.data = 0;
|
|
#endif
|
|
#endif
|
|
- dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
|
|
|
|
|
|
+ dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0);
|
|
|
|
+ if (!dsi_mem) {
|
|
|
|
+ DSSERR("can't get IORESOURCE_MEM DSI\n");
|
|
|
|
+ r = -EINVAL;
|
|
|
|
+ goto err1;
|
|
|
|
+ }
|
|
|
|
+ dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem));
|
|
if (!dsi.base) {
|
|
if (!dsi.base) {
|
|
DSSERR("can't ioremap DSI\n");
|
|
DSSERR("can't ioremap DSI\n");
|
|
r = -ENOMEM;
|
|
r = -ENOMEM;
|
|
goto err1;
|
|
goto err1;
|
|
}
|
|
}
|
|
|
|
+ dsi.irq = platform_get_irq(dsi.pdev, 0);
|
|
|
|
+ if (dsi.irq < 0) {
|
|
|
|
+ DSSERR("platform_get_irq failed\n");
|
|
|
|
+ r = -ENODEV;
|
|
|
|
+ goto err2;
|
|
|
|
+ }
|
|
|
|
|
|
- dsi.vdds_dsi_reg = dss_get_vdds_dsi();
|
|
|
|
- if (IS_ERR(dsi.vdds_dsi_reg)) {
|
|
|
|
- DSSERR("can't get VDDS_DSI regulator\n");
|
|
|
|
- r = PTR_ERR(dsi.vdds_dsi_reg);
|
|
|
|
|
|
+ r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED,
|
|
|
|
+ "OMAP DSI1", dsi.pdev);
|
|
|
|
+ if (r < 0) {
|
|
|
|
+ DSSERR("request_irq failed\n");
|
|
goto err2;
|
|
goto err2;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* DSI VCs initialization */
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) {
|
|
|
|
+ dsi.vc[i].mode = DSI_VC_MODE_L4;
|
|
|
|
+ dsi.vc[i].dssdev = NULL;
|
|
|
|
+ dsi.vc[i].vc_id = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dsi_calc_clock_param_ranges();
|
|
|
|
+
|
|
enable_clocks(1);
|
|
enable_clocks(1);
|
|
|
|
|
|
rev = dsi_read_reg(DSI_REVISION);
|
|
rev = dsi_read_reg(DSI_REVISION);
|
|
- printk(KERN_INFO "OMAP DSI rev %d.%d\n",
|
|
|
|
|
|
+ dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n",
|
|
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
|
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
|
|
|
|
|
enable_clocks(0);
|
|
enable_clocks(0);
|
|
@@ -3298,8 +3731,14 @@ err1:
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
-void dsi_exit(void)
|
|
|
|
|
|
+static void dsi_exit(void)
|
|
{
|
|
{
|
|
|
|
+ if (dsi.vdds_dsi_reg != NULL) {
|
|
|
|
+ regulator_put(dsi.vdds_dsi_reg);
|
|
|
|
+ dsi.vdds_dsi_reg = NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ free_irq(dsi.irq, dsi.pdev);
|
|
iounmap(dsi.base);
|
|
iounmap(dsi.base);
|
|
|
|
|
|
destroy_workqueue(dsi.workqueue);
|
|
destroy_workqueue(dsi.workqueue);
|
|
@@ -3307,3 +3746,41 @@ void dsi_exit(void)
|
|
DSSDBG("omap_dsi_exit\n");
|
|
DSSDBG("omap_dsi_exit\n");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* DSI1 HW IP initialisation */
|
|
|
|
+static int omap_dsi1hw_probe(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ int r;
|
|
|
|
+ dsi.pdev = pdev;
|
|
|
|
+ r = dsi_init(pdev);
|
|
|
|
+ if (r) {
|
|
|
|
+ DSSERR("Failed to initialize DSI\n");
|
|
|
|
+ goto err_dsi;
|
|
|
|
+ }
|
|
|
|
+err_dsi:
|
|
|
|
+ return r;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int omap_dsi1hw_remove(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ dsi_exit();
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct platform_driver omap_dsi1hw_driver = {
|
|
|
|
+ .probe = omap_dsi1hw_probe,
|
|
|
|
+ .remove = omap_dsi1hw_remove,
|
|
|
|
+ .driver = {
|
|
|
|
+ .name = "omapdss_dsi1",
|
|
|
|
+ .owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int dsi_init_platform_driver(void)
|
|
|
|
+{
|
|
|
|
+ return platform_driver_register(&omap_dsi1hw_driver);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void dsi_uninit_platform_driver(void)
|
|
|
|
+{
|
|
|
|
+ return platform_driver_unregister(&omap_dsi1hw_driver);
|
|
|
|
+}
|