From 50aa554329c97e159350bbfeee9b8a192da308b4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 3 May 2011 12:19:20 +0800 Subject: OMAP2: VIDEO: DSS: Use working TI code for HDMI This downgrades the incompatibly uplevelled parts of the OMAP2 DSS stuff to the working HDMI version that TI provided Signed-off-by: Andy Green --- drivers/video/omap2/dss/dsi.c | 815 +++++++++------------------------ drivers/video/omap2/dss/dss.c | 122 ++--- drivers/video/omap2/dss/dss.h | 6 + drivers/video/omap2/dss/dss_features.c | 152 ++---- drivers/video/omap2/dss/dss_features.h | 2 + drivers/video/omap2/dss/venc.c | 26 +- 6 files changed, 322 insertions(+), 801 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d4d07dcdc0a..0b943f68979 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -190,11 +190,19 @@ 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; + omap_dsi_isr_t isr; + void *arg; + u32 mask; }; +#define FINT_MAX 2100000 +#define FINT_MIN 750000 +#define REGN_MAX (1 << 7) +#define REGM_MAX ((1 << 11) - 1) +#define REGM_DISPC_MAX (1 << 4) +#define REGM_DSI_MAX (1 << 4) +#define LP_DIV_MAX ((1 << 13) - 1) + enum fifo_size { DSI_FIFO_SIZE_0 = 0, DSI_FIFO_SIZE_32 = 1, @@ -249,10 +257,8 @@ static struct unsigned pll_locked; - 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; + struct completion bta_completion; + void (*bta_callback)(void); int update_channel; struct dsi_update_region update_region; @@ -287,11 +293,6 @@ static struct spinlock_t irq_stats_lock; struct dsi_irq_stats irq_stats; #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; #ifdef DEBUG @@ -309,20 +310,6 @@ static inline u32 dsi_read_reg(const struct dsi_reg idx) return __raw_readl(dsi.base + idx.idx); } -static struct regulator *dsi_get_vdds_dsi(void) -{ - struct regulator *reg; - - if (dsi.vdds_dsi_reg != NULL) - return dsi.vdds_dsi_reg; - - reg = regulator_get(&dsi.pdev->dev, "vdds_dsi"); - if (!IS_ERR(reg)) - dsi.vdds_dsi_reg = reg; - - return reg; -} - void dsi_save_context(void) { @@ -349,11 +336,6 @@ static bool dsi_bus_is_locked(void) 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, int value) { @@ -423,9 +405,6 @@ static void dsi_perf_show(const char *name) static void print_irq_status(u32 status) { - if (status == 0) - return; - #ifndef VERBOSE_IRQ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) return; @@ -461,9 +440,6 @@ static void print_irq_status(u32 status) static void print_irq_status_vc(int channel, u32 status) { - if (status == 0) - return; - #ifndef VERBOSE_IRQ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) return; @@ -523,33 +499,26 @@ static void print_irq_status_cio(u32 status) printk("\n"); } -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS -static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus) +static int debug_irq; + +/* called from dss */ +static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) { + u32 irqstatus, vcstatus, ciostatus; int i; - spin_lock(&dsi.irq_stats_lock); + irqstatus = dsi_read_reg(DSI_IRQSTATUS); + + /* IRQ is not for us */ + if (!irqstatus) + return IRQ_NONE; +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock(&dsi.irq_stats_lock); dsi.irq_stats.irq_count++; 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 -static int debug_irq; - -static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) -{ - int i; - if (irqstatus & DSI_IRQ_ERROR_MASK) { DSSERR("DSI error, irqstatus %x\n", irqstatus); print_irq_status(irqstatus); @@ -560,88 +529,37 @@ static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) print_irq_status(irqstatus); } - 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); +#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] == 0) + if ((irqstatus & (1<isr_table_vc[i], - ARRAY_SIZE(isr_tables->isr_table_vc[i]), - vcstatus[i]); - } - - if (ciostatus != 0) - dsi_call_isrs(isr_tables->isr_table_cio, - ARRAY_SIZE(isr_tables->isr_table_cio), - ciostatus); -} - -static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) -{ - u32 irqstatus, vcstatus[4], ciostatus; - int i; - spin_lock(&dsi.irq_lock); + vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); - irqstatus = dsi_read_reg(DSI_IRQSTATUS); - - /* IRQ is not for us */ - if (!irqstatus) { - spin_unlock(&dsi.irq_lock); - return IRQ_NONE; - } +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); +#endif - dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); - /* flush posted write */ - dsi_read_reg(DSI_IRQSTATUS); + if (vcstatus & DSI_VC_IRQ_BTA) { + complete(&dsi.bta_completion); - for (i = 0; i < 4; ++i) { - if ((irqstatus & (1 << i)) == 0) { - vcstatus[i] = 0; - continue; + if (dsi.bta_callback) + dsi.bta_callback(); } - vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i)); + 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); + } - dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]); + dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); /* flush posted write */ dsi_read_reg(DSI_VC_IRQSTATUS(i)); } @@ -649,289 +567,99 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { 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); /* flush posted write */ dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); - } else { - ciostatus = 0; - } -#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; + 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); + } } - 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); - - /* flush posted writes */ - dsi_read_reg(enable_reg); - dsi_read_reg(status_reg); -} + dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); + /* flush posted write */ + dsi_read_reg(DSI_IRQSTATUS); -/* 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; +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_unlock(&dsi.irq_stats_lock); #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); + return IRQ_HANDLED; } static void _dsi_initialize_irq(void) { - 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; - - BUG_ON(isr == NULL); - - /* 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]; - - 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; - } - - if (free_idx == -1) - return -EBUSY; - - isr_data = &isr_array[free_idx]; - isr_data->isr = isr; - isr_data->arg = arg; - isr_data->mask = mask; - - 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; + u32 l; 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; + /* 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); - isr_data->isr = NULL; - isr_data->arg = NULL; - isr_data->mask = 0; + /* clear interrupt status */ + l = dsi_read_reg(DSI_IRQSTATUS); + dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); - return 0; + for (i = 0; i < 4; ++i) { + l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); + dsi_write_reg(DSI_VC_IRQSTATUS(i), l); } - return -EINVAL; -} - -static int dsi_register_isr(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, - ARRAY_SIZE(dsi.isr_tables.isr_table)); - - if (r == 0) - _omap_dsi_set_irqs(); - - spin_unlock_irqrestore(&dsi.irq_lock, flags); - - return r; -} - -static int dsi_unregister_isr(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, - ARRAY_SIZE(dsi.isr_tables.isr_table)); - - if (r == 0) - _omap_dsi_set_irqs(); - - spin_unlock_irqrestore(&dsi.irq_lock, flags); - - return r; -} - -static int dsi_register_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_register_isr(isr, arg, mask, - dsi.isr_tables.isr_table_vc[channel], - ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); + l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); + dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); - if (r == 0) - _omap_dsi_set_irqs_vc(channel); + /* 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); - spin_unlock_irqrestore(&dsi.irq_lock, flags); + l = DSI_VC_IRQ_ERROR_MASK; + for (i = 0; i < 4; ++i) + dsi_write_reg(DSI_VC_IRQENABLE(i), l); - return r; + l = DSI_CIO_IRQ_ERROR_MASK; + dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); } -static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, - u32 mask) +static u32 dsi_get_errors(void) { 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; + u32 e; + spin_lock_irqsave(&dsi.errors_lock, flags); + e = dsi.errors; + dsi.errors = 0; + spin_unlock_irqrestore(&dsi.errors_lock, flags); + return e; } -static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) +static void dsi_vc_enable_bta_irq(int channel) { - 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(); + u32 l; - spin_unlock_irqrestore(&dsi.irq_lock, flags); + dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); - return r; + l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); + l |= DSI_VC_IRQ_BTA; + dsi_write_reg(DSI_VC_IRQENABLE(channel), l); } -static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) +static void dsi_vc_disable_bta_irq(int channel) { - 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); + u32 l; - return r; -} - -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; + l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); + l &= ~DSI_VC_IRQ_BTA; + dsi_write_reg(DSI_VC_IRQENABLE(channel), l); } /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ @@ -1042,7 +770,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; - if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) + if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) return -EINVAL; dsi_fclk = dsi_fclk_rate(); @@ -1092,16 +820,16 @@ static int dsi_pll_power(enum dsi_pll_power_state state) static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, struct dsi_clock_info *cinfo) { - if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) + if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) return -EINVAL; - if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) + if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) return -EINVAL; - if (cinfo->regm_dispc > dsi.regm_dispc_max) + if (cinfo->regm_dispc > REGM_DISPC_MAX) return -EINVAL; - if (cinfo->regm_dsi > dsi.regm_dsi_max) + if (cinfo->regm_dsi > REGM_DSI_MAX) return -EINVAL; if (cinfo->use_sys_clk) { @@ -1120,7 +848,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); - if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) + if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) return -EINVAL; cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; @@ -1155,7 +883,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + max_dss_fck = dss_feat_get_max_dss_fck(); if (req_pck == dsi.cache_req_pck && dsi.cache_cinfo.clkin == dss_sys_clk) { @@ -1190,17 +918,17 @@ retry: /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ - for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { + for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { if (cur.highfreq == 0) cur.fint = cur.clkin / cur.regn; else cur.fint = cur.clkin / (2 * cur.regn); - if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) + if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) continue; /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ - for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { + for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { unsigned long a, b; a = 2 * cur.regm * (cur.clkin/1000); @@ -1212,7 +940,7 @@ retry: /* dsi_pll_hsdiv_dispc_clk(MHz) = * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ - for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max; + for (cur.regm_dispc = 1; cur.regm_dispc < REGM_DISPC_MAX; ++cur.regm_dispc) { struct dispc_clock_info cur_dispc; cur.dsi_pll_hsdiv_dispc_clk = @@ -1284,9 +1012,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) { int r = 0; u32 l; - int f = 0; - u8 regn_start, regn_end, regm_start, regm_end; - u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; + int f; DSSDBGF(); @@ -1331,43 +1057,32 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) 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 */ l = dsi_read_reg(DSI_PLL_CONFIGURATION1); l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ - /* 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->regn - 1, 7, 1); /* DSI_PLL_REGN */ + l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, - regm_dispc_start, regm_dispc_end); - /* DSIPROTO_CLOCK_DIV */ + 22, 19); /* DSI_CLOCK_DIV */ l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, - regm_dsi_start, regm_dsi_end); + 26, 23); /* DSIPROTO_CLOCK_DIV */ dsi_write_reg(DSI_PLL_CONFIGURATION1, l); - BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); - - if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { - f = cinfo->fint < 1000000 ? 0x3 : - cinfo->fint < 1250000 ? 0x4 : - cinfo->fint < 1500000 ? 0x5 : - cinfo->fint < 1750000 ? 0x6 : - 0x7; - } + BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); + if (cinfo->fint < 1000000) + f = 0x3; + else if (cinfo->fint < 1250000) + f = 0x4; + else if (cinfo->fint < 1500000) + f = 0x5; + else if (cinfo->fint < 1750000) + f = 0x6; + else + f = 0x7; l = dsi_read_reg(DSI_PLL_CONFIGURATION2); - - if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) - 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_sys_clk ? 0 : 1, 11, 11); /* DSI_PLL_CLKSEL */ l = FLD_MOD(l, cinfo->highfreq, @@ -1423,6 +1138,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, 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 @@ -1440,6 +1156,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, dsi.vdds_dsi_reg = vdds_dsi; } +#endif enable_clocks(1); dsi_enable_pll_clock(1); @@ -1885,6 +1602,9 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev) DSSDBG("dsi_complexio_init\n"); + /* CIO_CLK_ICG, enable L3 clk to CIO */ + REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); + /* A dummy read using the SCP interface to any DSIPHY register is * required after DSIPHY reset to complete the reset of the DSI complex * I/O. */ @@ -1909,12 +1629,10 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev) goto err; } - if (dss_has_feature(FEAT_DSI_LDO_STATUS)) { - if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { - DSSERR("ComplexIO LDO power down.\n"); - r = -ENODEV; - goto err; - } + if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { + DSSERR("ComplexIO LDO power down.\n"); + r = -ENODEV; + goto err; } dsi_complexio_timings(); @@ -2045,114 +1763,6 @@ static int dsi_force_tx_stop_mode_io(void) return 0; } -static bool dsi_vc_is_enabled(int channel) -{ - return REG_GET(DSI_VC_CTRL(channel), 0, 0); -} - -static void dsi_packet_sent_handler_vp(void *data, u32 mask) -{ - const int channel = dsi.update_channel; - u8 bit = dsi.te_enabled ? 30 : 31; - - if (REG_GET(DSI_VC_TE(channel), bit, bit) == 0) - complete((struct completion *)data); -} - -static int dsi_sync_vc_vp(int channel) -{ - int r = 0; - u8 bit; - - DECLARE_COMPLETION_ONSTACK(completion); - - bit = dsi.te_enabled ? 30 : 31; - - r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_vp, - &completion, DSI_VC_IRQ_PACKET_SENT); - if (r) - goto err0; - - /* Wait for completion only if TE_EN/TE_START is still set */ - if (REG_GET(DSI_VC_TE(channel), bit, bit)) { - if (wait_for_completion_timeout(&completion, - msecs_to_jiffies(10)) == 0) { - DSSERR("Failed to complete previous frame transfer\n"); - r = -EIO; - goto err1; - } - } - - dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, - &completion, DSI_VC_IRQ_PACKET_SENT); - - return 0; -err1: - dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, &completion, - DSI_VC_IRQ_PACKET_SENT); -err0: - return r; -} - -static void dsi_packet_sent_handler_l4(void *data, u32 mask) -{ - const int channel = dsi.update_channel; - - if (REG_GET(DSI_VC_CTRL(channel), 5, 5) == 0) - complete((struct completion *)data); -} - -static int dsi_sync_vc_l4(int channel) -{ - int r = 0; - - DECLARE_COMPLETION_ONSTACK(completion); - - r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_l4, - &completion, DSI_VC_IRQ_PACKET_SENT); - if (r) - goto err0; - - /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */ - if (REG_GET(DSI_VC_CTRL(channel), 5, 5)) { - if (wait_for_completion_timeout(&completion, - msecs_to_jiffies(10)) == 0) { - DSSERR("Failed to complete previous l4 transfer\n"); - r = -EIO; - goto err1; - } - } - - dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4, - &completion, DSI_VC_IRQ_PACKET_SENT); - - return 0; -err1: - dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4, - &completion, DSI_VC_IRQ_PACKET_SENT); -err0: - return r; -} - -static int dsi_sync_vc(int channel) -{ - WARN_ON(!dsi_bus_is_locked()); - - WARN_ON(in_interrupt()); - - if (!dsi_vc_is_enabled(channel)) - return 0; - - switch (dsi.vc[channel].mode) { - case DSI_VC_MODE_VP: - return dsi_sync_vc_vp(channel); - case DSI_VC_MODE_L4: - return dsi_sync_vc_l4(channel); - default: - BUG(); - } -} - static int dsi_vc_enable(int channel, bool enable) { DSSDBG("dsi_vc_enable channel %d, enable %d\n", @@ -2189,8 +1799,6 @@ static void dsi_vc_initial_config(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)) - r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ @@ -2205,8 +1813,6 @@ static int dsi_vc_config_l4(int channel) DSSDBGF("%d", channel); - dsi_sync_vc(channel); - dsi_vc_enable(channel, 0); /* VC_BUSY */ @@ -2217,10 +1823,6 @@ static int dsi_vc_config_l4(int channel) REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ - /* DCS_CMD_ENABLE */ - if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) - REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 30, 30); - dsi_vc_enable(channel, 1); dsi.vc[channel].mode = DSI_VC_MODE_L4; @@ -2235,8 +1837,6 @@ static int dsi_vc_config_vp(int channel) DSSDBGF("%d", channel); - dsi_sync_vc(channel); - dsi_vc_enable(channel, 0); /* VC_BUSY */ @@ -2247,10 +1847,6 @@ static int dsi_vc_config_vp(int channel) REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ - /* DCS_CMD_ENABLE */ - if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) - REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 30, 30); - dsi_vc_enable(channel, 1); dsi.vc[channel].mode = DSI_VC_MODE_VP; @@ -2375,44 +1971,33 @@ static int dsi_vc_send_bta(int channel) int dsi_vc_send_bta_sync(int channel) { - DECLARE_COMPLETION_ONSTACK(completion); int r = 0; u32 err; - r = dsi_register_isr_vc(channel, dsi_completion_handler, - &completion, DSI_VC_IRQ_BTA); - if (r) - goto err0; + INIT_COMPLETION(dsi.bta_completion); - r = dsi_register_isr(dsi_completion_handler, &completion, - DSI_IRQ_ERROR_MASK); - if (r) - goto err1; + dsi_vc_enable_bta_irq(channel); r = dsi_vc_send_bta(channel); if (r) - goto err2; + goto err; - if (wait_for_completion_timeout(&completion, + if (wait_for_completion_timeout(&dsi.bta_completion, msecs_to_jiffies(500)) == 0) { DSSERR("Failed to receive BTA\n"); r = -EIO; - goto err2; + goto err; } err = dsi_get_errors(); if (err) { DSSERR("Error while sending BTA: %x\n", err); r = -EIO; - goto err2; + goto err; } -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: +err: + dsi_vc_disable_bta_irq(channel); + return r; } EXPORT_SYMBOL(dsi_vc_send_bta_sync); @@ -2906,11 +2491,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) 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)) { - r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ - /* DCS_CMD_CODE, 1=start, 0=continue */ - r = FLD_MOD(r, 0, 25, 25); - } + r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ + r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ dsi_write_reg(DSI_CTRL, r); @@ -3231,14 +2813,30 @@ static void dsi_te_timeout(unsigned long arg) static void dsi_handle_framedone(int error) { + const int channel = dsi.update_channel; + + cancel_delayed_work(&dsi.framedone_timeout_work); + + dsi_vc_disable_bta_irq(channel); + /* SIDLEMODE back to smart-idle */ dispc_enable_sidle(); + dsi.bta_callback = NULL; + if (dsi.te_enabled) { /* enable LP_RX_TO again after the TE */ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ } + /* RX_FIFO_NOT_EMPTY */ + if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { + DSSERR("Received error during frame transfer:\n"); + dsi_vc_flush_receive_data(channel); + if (!error) + error = -EIO; + } + dsi.framedone_callback(error, dsi.framedone_data); if (!error) @@ -3259,20 +2857,57 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) dsi_handle_framedone(-ETIMEDOUT); } +static void dsi_framedone_bta_callback(void) +{ + dsi_handle_framedone(0); + +#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC + dispc_fake_vsync_irq(); +#endif +} + static void dsi_framedone_irq_callback(void *data, u32 mask) { + const int channel = dsi.update_channel; + int r; + /* Note: We get FRAMEDONE when DISPC has finished sending pixels and * turns itself off. However, DSI still has the pixels in its buffers, * and is sending the data. */ - __cancel_delayed_work(&dsi.framedone_timeout_work); + if (dsi.te_enabled) { + /* enable LP_RX_TO again after the TE */ + REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ + } - dsi_handle_framedone(0); + /* Send BTA after the frame. We need this for the TE to work, as TE + * trigger is only sent for BTAs without preceding packet. Thus we need + * to BTA after the pixel packets so that next BTA will cause TE + * trigger. + * + * This is not needed when TE is not in use, but we do it anyway to + * make sure that the transfer has been completed. It would be more + * optimal, but more complex, to wait only just before starting next + * transfer. + * + * Also, as there's no interrupt telling when the transfer has been + * done and the channel could be reconfigured, the only way is to + * busyloop until TE_SIZE is zero. With BTA we can do this + * asynchronously. + * */ -#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC - dispc_fake_vsync_irq(); -#endif + dsi.bta_callback = dsi_framedone_bta_callback; + + barrier(); + + dsi_vc_enable_bta_irq(channel); + + r = dsi_vc_send_bta(channel); + if (r) { + DSSERR("BTA after framedone failed\n"); + dsi_handle_framedone(-EIO); + } } int omap_dsi_prepare_update(struct omap_dss_device *dssdev, @@ -3449,10 +3084,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) { int r; - /* The SCPClk is required for both PLL and CIO registers on OMAP4 */ - /* CIO_CLK_ICG, enable L3 clk to CIO */ - REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); - _dsi_print_reset_status(); r = dsi_pll_init(dssdev, true, true); @@ -3465,8 +3096,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); - dss_select_lcd_clk_source(dssdev->manager->id, - DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); DSSDBG("PLL OK\n"); @@ -3723,24 +3352,12 @@ void dsi_wait_pll_hsdiv_dsi_active(void) 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); -} - static int dsi_init(struct platform_device *pdev) { u32 rev; int r, i; struct resource *dsi_mem; - spin_lock_init(&dsi.irq_lock); spin_lock_init(&dsi.errors_lock); dsi.errors = 0; @@ -3749,6 +3366,8 @@ static int dsi_init(struct platform_device *pdev) dsi.irq_stats.last_reset = jiffies; #endif + init_completion(&dsi.bta_completion); + mutex_init(&dsi.lock); sema_init(&dsi.bus_lock, 1); @@ -3789,12 +3408,6 @@ static int dsi_init(struct platform_device *pdev) DSSERR("request_irq failed\n"); goto err2; } - dsi.vdds_dsi_reg = dsi_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); - goto err2; - } /* DSI VCs initialization */ for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { @@ -3803,8 +3416,6 @@ static int dsi_init(struct platform_device *pdev) dsi.vc[i].vc_id = 0; } - dsi_calc_clock_param_ranges(); - enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 3f1fee63c67..7f846996dc3 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -82,10 +82,10 @@ static struct { u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; -static const char * const dss_generic_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", - [DSS_CLK_SRC_FCK] = "DSS_FCK", +static const struct dss_clk_source_name dss_generic_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI_PLL_HSDIV_DISPC" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI_PLL_HSDIV_DSI" }, + { DSS_CLK_SRC_FCK, "DSS_FCK" }, }; static void dss_clk_enable_all_no_ctx(void); @@ -232,47 +232,37 @@ void dss_sdi_disable(void) const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) { - return dss_generic_clk_source_names[clk_src]; + return dss_generic_clk_source_names[clk_src].clksrc_name; } void dss_dump_clocks(struct seq_file *s) { unsigned long dpll4_ck_rate; unsigned long dpll4_m4_ck_rate; - const char *fclk_name, *fclk_real_name; - unsigned long fclk_rate; dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - seq_printf(s, "- DSS -\n"); - - fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); - fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); - fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); + dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); - if (dss.dpll4_m4_ck) { - dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); + seq_printf(s, "- DSS -\n"); - seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); + seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); - if (cpu_is_omap3630() || cpu_is_omap44xx()) - seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", - fclk_name, fclk_real_name, - dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - fclk_rate); - else - seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", - fclk_name, fclk_real_name, - dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - fclk_rate); - } else { - seq_printf(s, "%s (%s) = %lu\n", - fclk_name, fclk_real_name, - fclk_rate); - } + if (cpu_is_omap3630() || cpu_is_omap44xx()) + seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", + dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK), + dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK), + dpll4_ck_rate, + dpll4_ck_rate / dpll4_m4_ck_rate, + dss_clk_get_rate(DSS_CLK_FCK)); + else + seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", + dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK), + dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK), + dpll4_ck_rate, + dpll4_ck_rate / dpll4_m4_ck_rate, + dss_clk_get_rate(DSS_CLK_FCK)); dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } @@ -392,43 +382,34 @@ enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) /* calculate clock rates using dividers in cinfo */ int dss_calc_clock_rates(struct dss_clock_info *cinfo) { - if (dss.dpll4_m4_ck) { - unsigned long prate; - u16 fck_div_max = 16; + unsigned long prate; + u16 fck_div_max = 16; - if (cpu_is_omap3630() || cpu_is_omap44xx()) - fck_div_max = 32; + if (cpu_is_omap3630() || cpu_is_omap44xx()) + fck_div_max = 32; - if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0) - return -EINVAL; + if ((cinfo->fck_div > fck_div_max) || cinfo->fck_div == 0) + return -EINVAL; - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - cinfo->fck = prate / cinfo->fck_div; - } else { - if (cinfo->fck_div != 0) - return -EINVAL; - cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); - } + cinfo->fck = prate / cinfo->fck_div; return 0; } int dss_set_clock_div(struct dss_clock_info *cinfo) { - if (dss.dpll4_m4_ck) { - unsigned long prate; - int r; + unsigned long prate; + int r; + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); DSSDBG("dpll4_m4 = %ld\n", prate); r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); if (r) return r; - } else { - if (cinfo->fck_div != 0) - return -EINVAL; } DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); @@ -440,11 +421,9 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) { cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); - if (dss.dpll4_m4_ck) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { unsigned long prate; - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - if (cpu_is_omap3630() || cpu_is_omap44xx()) cinfo->fck_div = prate / (cinfo->fck); else @@ -458,7 +437,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) unsigned long dss_get_dpll4_rate(void) { - if (dss.dpll4_m4_ck) + if (cpu_is_omap34xx() || cpu_is_omap44xx()) return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); else return 0; @@ -481,7 +460,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, prate = dss_get_dpll4_rate(); - max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + max_dss_fck = dss_feat_get_max_dss_fck(); fck = dss_clk_get_rate(DSS_CLK_FCK); if (req_pck == dss.cache_req_pck && @@ -507,7 +486,7 @@ retry: memset(&best_dss, 0, sizeof(best_dss)); memset(&best_dispc, 0, sizeof(best_dispc)); - if (dss.dpll4_m4_ck == NULL) { + if (cpu_is_omap24xx()) { struct dispc_clock_info cur_dispc; /* XXX can we change the clock on omap2? */ fck = dss_clk_get_rate(DSS_CLK_FCK); @@ -522,7 +501,8 @@ retry: best_dispc = cur_dispc; goto found; - } else { + } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { + if (cpu_is_omap3630() || cpu_is_omap44xx()) fck_div_max = 32; @@ -557,6 +537,8 @@ retry: goto found; } } + } else { + BUG(); } found: @@ -639,7 +621,6 @@ static int dss_init(void) int r; u32 rev; struct resource *dss_mem; - struct clk *dpll4_m4_ck; dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); if (!dss_mem) { @@ -680,26 +661,23 @@ static int dss_init(void) REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif + if (cpu_is_omap34xx()) { - dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); - if (IS_ERR(dpll4_m4_ck)) { + dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dss.dpll4_m4_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(dpll4_m4_ck); + r = PTR_ERR(dss.dpll4_m4_ck); goto fail1; } } else if (cpu_is_omap44xx()) { - dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); - if (IS_ERR(dpll4_m4_ck)) { + dss.dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); + if (IS_ERR(dss.dpll4_m4_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(dpll4_m4_ck); + r = PTR_ERR(dss.dpll4_m4_ck); goto fail1; } - } else { /* omap24xx */ - dpll4_m4_ck = NULL; } - dss.dpll4_m4_ck = dpll4_m4_ck; - dss.dsi_clk_source = DSS_CLK_SRC_FCK; dss.dispc_clk_source = DSS_CLK_SRC_FCK; dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; @@ -721,7 +699,7 @@ fail0: static void dss_exit(void) { - if (dss.dpll4_m4_ck) + if (cpu_is_omap34xx() || cpu_is_omap44xx()) clk_put(dss.dpll4_m4_ck); iounmap(dss.base); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index c2f582bb19c..05ccd005e26 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -126,6 +126,12 @@ enum dss_clk_source { * OMAP4: DSS_FCLK */ }; +/* Correlates clock source name and dss_clk_source member */ +struct dss_clk_source_name { + enum dss_clk_source clksrc; + const char *clksrc_name; +}; + enum dss_hdmi_venc_clk_source_select { DSS_VENC_TV_CLK = 0, DSS_HDMI_M_PCLK = 1, diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index b4f63d01180..ea18690a9c8 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -30,13 +30,10 @@ /* Defines a generic omap register field */ struct dss_reg_field { + enum dss_feat_reg_field id; u8 start, end; }; -struct dss_param_range { - int min, max; -}; - struct omap_dss_features { const struct dss_reg_field *reg_fields; const int num_reg_fields; @@ -45,58 +42,46 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; + const unsigned long max_dss_fck; const enum omap_display_type *supported_displays; const enum omap_color_mode *supported_color_modes; - const char * const *clksrc_names; - const struct dss_param_range *dss_params; + const struct dss_clk_source_name *clksrc_names; }; /* This struct is assigned to one of the below during initialization */ static struct omap_dss_features *omap_current_dss_features; static const struct dss_reg_field omap2_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 11, 0 }, - [FEAT_REG_FIRVINC] = { 27, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, - [FEAT_REG_FIFOSIZE] = { 8, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, - [FEAT_REG_DSIPLL_REGN] = { 0, 0 }, - [FEAT_REG_DSIPLL_REGM] = { 0, 0 }, - [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 }, - [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 }, + { FEAT_REG_FIRHINC, 11, 0 }, + { FEAT_REG_FIRVINC, 27, 16 }, + { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 }, + { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 }, + { FEAT_REG_FIFOSIZE, 8, 0 }, + { FEAT_REG_HORIZONTALACCU, 9, 0 }, + { FEAT_REG_VERTICALACCU, 25, 16 }, + { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, }; static const struct dss_reg_field omap3_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, - [FEAT_REG_FIFOSIZE] = { 10, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, - [FEAT_REG_VERTICALACCU] = { 25, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, - [FEAT_REG_DSIPLL_REGN] = { 7, 1 }, - [FEAT_REG_DSIPLL_REGM] = { 18, 8 }, - [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 }, - [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, + { FEAT_REG_FIRHINC, 12, 0 }, + { FEAT_REG_FIRVINC, 28, 16 }, + { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 }, + { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 }, + { FEAT_REG_FIFOSIZE, 10, 0 }, + { FEAT_REG_HORIZONTALACCU, 9, 0 }, + { FEAT_REG_VERTICALACCU, 25, 16 }, + { FEAT_REG_DISPC_CLK_SWITCH, 0, 0 }, }; static const struct dss_reg_field omap4_dss_reg_fields[] = { - [FEAT_REG_FIRHINC] = { 12, 0 }, - [FEAT_REG_FIRVINC] = { 28, 16 }, - [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, - [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, - [FEAT_REG_FIFOSIZE] = { 15, 0 }, - [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, - [FEAT_REG_VERTICALACCU] = { 26, 16 }, - [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, - [FEAT_REG_DSIPLL_REGN] = { 8, 1 }, - [FEAT_REG_DSIPLL_REGM] = { 20, 9 }, - [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 }, - [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, + { FEAT_REG_FIRHINC, 12, 0 }, + { FEAT_REG_FIRVINC, 28, 16 }, + { FEAT_REG_FIFOLOWTHRESHOLD, 15, 0 }, + { FEAT_REG_FIFOHIGHTHRESHOLD, 31, 16 }, + { FEAT_REG_FIFOSIZE, 15, 0 }, + { FEAT_REG_HORIZONTALACCU, 10, 0 }, + { FEAT_REG_VERTICALACCU, 26, 16 }, + { FEAT_REG_DISPC_CLK_SWITCH, 9, 8 }, }; static const enum omap_display_type omap2_dss_supported_displays[] = { @@ -179,52 +164,22 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, }; -static const char * const omap2_dss_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", - [DSS_CLK_SRC_FCK] = "DSS_FCLK1", -}; - -static const char * const omap3_dss_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", - [DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", -}; - -static const char * const omap4_dss_clk_source_names[] = { - [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", - [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", - [DSS_CLK_SRC_FCK] = "DSS_FCLK", +static const struct dss_clk_source_name omap2_dss_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "N/A" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "N/A" }, + { DSS_CLK_SRC_FCK, "DSS_FCLK1" }, }; -static const struct dss_param_range omap2_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, - [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, - [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, - [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, - [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, - [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, - [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, +static const struct dss_clk_source_name omap3_dss_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI1_PLL_FCLK" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI2_PLL_FCLK" }, + { DSS_CLK_SRC_FCK, "DSS1_ALWON_FCLK" }, }; -static const struct dss_param_range omap3_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, - [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, - [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, - [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, - [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, - [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, - [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, -}; - -static const struct dss_param_range omap4_dss_param_range[] = { - [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, - [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, - [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, - [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, - [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, - [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, - [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, +static const struct dss_clk_source_name omap4_dss_clk_source_names[] = { + { DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "PLL1_CLK1" }, + { DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "PLL1_CLK2" }, + { DSS_CLK_SRC_FCK, "DSS_FCLK" }, }; /* OMAP2 DSS Features */ @@ -239,10 +194,10 @@ static struct omap_dss_features omap2_dss_features = { .num_mgrs = 2, .num_ovls = 3, + .max_dss_fck = 173000000, .supported_displays = omap2_dss_supported_displays, .supported_color_modes = omap2_dss_supported_color_modes, .clksrc_names = omap2_dss_clk_source_names, - .dss_params = omap2_dss_param_range, }; /* OMAP3 DSS Features */ @@ -254,15 +209,14 @@ static struct omap_dss_features omap3430_dss_features = { FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | - FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | - FEAT_DSI_PLL_FREQSEL | FEAT_DSI_LDO_STATUS, + FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF, .num_mgrs = 2, .num_ovls = 3, + .max_dss_fck = 173000000, .supported_displays = omap3430_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap3_dss_clk_source_names, - .dss_params = omap3_dss_param_range, }; static struct omap_dss_features omap3630_dss_features = { @@ -274,15 +228,14 @@ static struct omap_dss_features omap3630_dss_features = { FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | - FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL | - FEAT_DSI_LDO_STATUS, + FEAT_RESIZECONF, .num_mgrs = 2, .num_ovls = 3, + .max_dss_fck = 173000000, .supported_displays = omap3630_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap3_dss_clk_source_names, - .dss_params = omap3_dss_param_range, }; /* OMAP4 DSS Features */ @@ -293,15 +246,14 @@ static struct omap_dss_features omap4_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | - FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | - FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH, + FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC, .num_mgrs = 3, .num_ovls = 3, + .max_dss_fck = 186000000, .supported_displays = omap4_dss_supported_displays, .supported_color_modes = omap3_dss_supported_color_modes, .clksrc_names = omap4_dss_clk_source_names, - .dss_params = omap4_dss_param_range, }; /* Functions returning values related to a DSS feature */ @@ -315,14 +267,10 @@ int dss_feat_get_num_ovls(void) return omap_current_dss_features->num_ovls; } -unsigned long dss_feat_get_param_min(enum dss_range_param param) -{ - return omap_current_dss_features->dss_params[param].min; -} - -unsigned long dss_feat_get_param_max(enum dss_range_param param) +/* Max supported DSS FCK in Hz */ +unsigned long dss_feat_get_max_dss_fck(void) { - return omap_current_dss_features->dss_params[param].max; + return omap_current_dss_features->max_dss_fck; } enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) @@ -344,7 +292,7 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, const char *dss_feat_get_clk_source_name(enum dss_clk_source id) { - return omap_current_dss_features->clksrc_names[id]; + return omap_current_dss_features->clksrc_names[id].clksrc_name; } /* DSS has_feature check */ diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index c5c0b4001ab..2601626519c 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -77,6 +77,8 @@ int dss_feat_get_num_mgrs(void); int dss_feat_get_num_ovls(void); unsigned long dss_feat_get_param_min(enum dss_range_param param); unsigned long dss_feat_get_param_max(enum dss_range_param param); +/* HDMI from Seb comapat */ +unsigned long dss_feat_get_max_dss_fck(void); enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); bool dss_feat_color_mode_supported(enum omap_plane plane, diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 618b051278a..43009e57cd3 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -305,17 +305,6 @@ static inline u32 venc_read_reg(int idx) return l; } -static struct regulator *venc_get_vdda_dac(void) -{ - struct regulator *reg; - - reg = regulator_get(&venc.pdev->dev, "vdda_dac"); - if (!IS_ERR(reg)) - venc.vdda_dac_reg = reg; - - return reg; -} - static void venc_write_config(const struct venc_config *config) { DSSDBG("write venc conf\n"); @@ -747,17 +736,10 @@ static int omap_venchw_probe(struct platform_device *pdev) return -ENOMEM; } - venc.vdda_dac_reg = venc_get_vdda_dac(); - if (IS_ERR(venc.vdda_dac_reg)) { - iounmap(venc.base); - DSSERR("can't get VDDA_DAC regulator\n"); - return PTR_ERR(venc.vdda_dac_reg); - } - venc_enable_clocks(1); rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); - printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); + dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); venc_enable_clocks(0); @@ -787,16 +769,10 @@ static struct platform_driver omap_venchw_driver = { int venc_init_platform_driver(void) { - if (cpu_is_omap44xx()) - return 0; - return platform_driver_register(&omap_venchw_driver); } void venc_uninit_platform_driver(void) { - if (cpu_is_omap44xx()) - return; - return platform_driver_unregister(&omap_venchw_driver); } -- cgit v1.2.3