diff options
author | G, Manjunath Kondaiah <manjugk@ti.com> | 2010-10-29 16:19:10 +0530 |
---|---|---|
committer | G, Manjunath Kondaiah <manjugk@ti.com> | 2010-10-29 16:19:32 +0530 |
commit | 29e973b87c89e22a8ee95ee38afb0039a395d50d (patch) | |
tree | 0709d8db8e4e1fd445c944d0b157104d35b5e50f | |
parent | 08e5ff41d66926d88ef166ca53f6972753fbb360 (diff) | |
parent | 80b87dcb1b6167f303e617fdb7c70d814b2468d5 (diff) |
Merge branch 'Display changes' into L24.11ti-2.6.35-omap4-L24.11-p1
-rw-r--r-- | arch/arm/plat-omap/include/plat/display.h | 33 | ||||
-rw-r--r-- | drivers/media/video/omap/omap_vout.c | 214 | ||||
-rw-r--r-- | drivers/media/video/omap/omap_wb.c | 12 | ||||
-rw-r--r--[-rwxr-xr-x] | drivers/video/omap2/dss/core.c | 26 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 559 | ||||
-rw-r--r-- | drivers/video/omap2/dss/display.c | 23 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.c | 19 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 4 | ||||
-rw-r--r-- | drivers/video/omap2/dss/edid.c | 9 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 56 | ||||
-rw-r--r-- | drivers/video/omap2/dss/manager.c | 47 | ||||
-rw-r--r-- | drivers/video/omap2/dss/overlay.c | 14 |
12 files changed, 567 insertions, 449 deletions
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 6a1eeaf0b36d..122cea0b7347 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -264,10 +264,17 @@ enum omap_writeback_capturemode { }; enum device_n_buffer_type { - PBUF_PDEV = 0, - PBUF_IDEV = 1, - IBUF_IDEV = 2, - IBUF_PDEV = 3, + OMAP_FLAG_IDEV = 1, /* interlaced device */ + OMAP_FLAG_IBUF = 2, /* sequentially interlaced buffer */ + OMAP_FLAG_ISWAP = 4, /* bottom-top interlacing */ + + PBUF_PDEV = 0, + PBUF_IDEV = OMAP_FLAG_IDEV, + PBUF_IDEV_SWAP = OMAP_FLAG_IDEV | OMAP_FLAG_ISWAP, + IBUF_IDEV = OMAP_FLAG_IBUF | OMAP_FLAG_IDEV, + IBUF_IDEV_SWAP = OMAP_FLAG_IBUF | OMAP_FLAG_IDEV | OMAP_FLAG_ISWAP, + IBUF_PDEV = OMAP_FLAG_IBUF, + IBUF_PDEV_SWAP = OMAP_FLAG_IBUF | OMAP_FLAG_ISWAP, }; /* RFBI */ @@ -410,7 +417,6 @@ struct omap_overlay_info { enum omap_overlay_zorder zorder; u32 p_uv_addr; /* relevant for NV12 format only */ enum device_n_buffer_type field; - u16 pic_width; /* for interlacing with cropping this is required */ u16 pic_height; /* for interlacing with cropping this is required */ }; @@ -772,17 +778,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, int omap_rfbi_update(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h, void (*callback)(void *), void *data); -void calc_tiler_row_rotation(u8 rotation, - u16 width, - enum omap_color_mode color_mode, - int y_decim, - s32 *row_inc, - unsigned *offset1, - enum device_n_buffer_type ilace, - u16 pic_width, - u16 pic_height); - -void change_base_address(u32 offset, u16 *flag, int id); -u16 *get_offset_cnt(int id, u32 *offset); -int nature_of_hdmi(void); + +void change_base_address(int id, u32 p_uv_addr); +bool is_hdmi_interlaced(void); + #endif diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index c986302aa368..32b267e00acd 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -1051,73 +1051,63 @@ int omapvid_apply_changes(struct omap_vout_device *vout) return 0; } +/* This function inplements the interlace logic for VENC & ilace HDMI. It + * retruns '1' in case of a frame being completely displayed and signals to + * queue another frame whereas '0' means only half of the frame is only + * displayed and the remaing half is yet to be displayed */ static int interlace_display(struct omap_vout_device *vout, u32 irqstatus, - struct timeval timevalue, u32 flags) + struct timeval timevalue) { - unsigned long fid; + unsigned long fid; if (vout->first_int) { vout->first_int = 0; - spin_unlock_irqrestore(&vout->vbq_lock, flags); return 0; } - if (irqstatus & DISPC_IRQ_EVSYNC_ODD) { + if (irqstatus & DISPC_IRQ_EVSYNC_ODD) fid = 1; - } else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) { + else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) fid = 0; - } else { - spin_unlock_irqrestore(&vout->vbq_lock, flags); + else return 0; - } + vout->field_id ^= 1; if (fid != vout->field_id) { - if (0 == fid) - vout->field_id = fid; - - spin_unlock_irqrestore(&vout->vbq_lock, flags); - return 0; - } - if (0 == fid) { - if (vout->cur_frm == vout->next_frm) { - spin_unlock_irqrestore(&vout->vbq_lock, flags); + /* reset field ID */ + vout->field_id = 0; + } else if (0 == fid) { + if (vout->cur_frm == vout->next_frm) return 0; - } + vout->cur_frm->ts = timevalue; vout->cur_frm->state = VIDEOBUF_DONE; wake_up_interruptible(&vout->cur_frm->done); vout->cur_frm = vout->next_frm; - return 1; - } else if (1 == fid) { - if (list_empty(&vout->dma_queue) || - (vout->cur_frm != vout->next_frm)) { - spin_unlock_irqrestore(&vout->vbq_lock, flags); - return 0; - } - return 2; - } - return 3; + } else { + if (list_empty(&vout->dma_queue) || + vout->cur_frm != vout->next_frm) + return 0; + } + return vout->field_id; } -static int i_to_p_base_address_change(struct omap_vout_device *vout, - unsigned long flags) +/* This returns the the infromation of level of completion of display of + the complete frame */ +static int i_to_p_base_address_change(struct omap_vout_device *vout) { - u16 *cnt; - u32 offset; + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + ovid = &(vout->vid_info); + ovl = ovid->overlays[0]; - struct omap_overlay *ovl; - struct omapvideo_info *ovid; + if (vout->field_id == 0) { + change_base_address(ovl->id, ovl->info.p_uv_addr); + dispc_go(ovl->manager->device->channel); + } + vout->field_id ^= 1; + return vout->field_id; +} - ovid = &(vout->vid_info); - ovl = ovid->overlays[0]; - cnt = get_offset_cnt(ovl->id, &offset); - change_base_address(offset, cnt, ovl->id); - if (*cnt == 1) { - *cnt = 2; - spin_unlock_irqrestore(&vout->vbq_lock, flags); - return 1; - } - return 0; -} void omap_vout_isr(void *arg, unsigned int irqstatus) { @@ -1162,20 +1152,20 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) case OMAP_DISPLAY_TYPE_DSI: if (!(irqstatus & irq)) goto vout_isr_err; - else if (ovl->info.field == IBUF_PDEV) { - if ((irq == DISPC_IRQ_FRAMEDONE) || - (irq == DISPC_IRQ_FRAMEDONE2)) { - ret = i_to_p_base_address_change(vout, flags); - if (ret == 1) { - dispc_go(cur_display->channel); - return; - } - } + + /* display 2nd field for interlaced buffers if progressive */ + if ((ovl->info.field & OMAP_FLAG_IBUF) && + !(ovl->info.field & OMAP_FLAG_IDEV) && + (irq == DISPC_IRQ_FRAMEDONE || + irq == DISPC_IRQ_FRAMEDONE2)) { + if (i_to_p_base_address_change(vout)) + goto vout_isr_err; } break; case OMAP_DISPLAY_TYPE_DPI: if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) goto vout_isr_err; + #ifdef CONFIG_PANEL_PICO_DLP if (dispc_go_busy(OMAP_DSS_CHANNEL_LCD2)) { printk(KERN_INFO "dpi busy %d\n", cur_display->type); @@ -1185,37 +1175,27 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) break; #ifdef CONFIG_OMAP2_DSS_HDMI case OMAP_DISPLAY_TYPE_HDMI: - if (ovl->info.field == PBUF_PDEV) { - if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) + if (ovl->info.field & OMAP_FLAG_IDEV) { + if (interlace_display(vout, irqstatus, timevalue)) + goto intlace; + else goto vout_isr_err; - } else if (ovl->info.field == IBUF_PDEV) { + } else if (ovl->info.field & OMAP_FLAG_IBUF) { if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) { - ret = i_to_p_base_address_change(vout, flags); - if (ret == 1) { - dispc_go(cur_display->channel); - return; - } - } - } else if (ovl->info.field == IBUF_IDEV) { - ret = interlace_display(vout, irqstatus, - timevalue, flags); - if (ret == 0) - return; - else if (ret == 1) + if (i_to_p_base_address_change(vout)) goto vout_isr_err; - else if (ret == 2) - goto intlace; - } - break; + } + } else { + if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) + goto vout_isr_err; + } + break; #else case OMAP_DISPLAY_TYPE_VENC: - ret = interlace_display(vout, irqstatus, timevalue, flags); - if (ret == 0) - return; - else if (ret == 1) - goto vout_isr_err; - else if (ret == 2) + if (interlace_display(vout, irqstatus, timevalue)) goto intlace; + else + goto vout_isr_err; #endif default: goto vout_isr_err; @@ -1236,7 +1216,7 @@ wb: intlace: vout->next_frm = list_entry(vout->dma_queue.next, - struct videobuf_buffer, queue); + struct videobuf_buffer, queue); list_del(&vout->next_frm->queue); vout->next_frm->state = VIDEOBUF_ACTIVE; @@ -1890,9 +1870,8 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, struct omap_video_timings *timing; struct omap_vout_device *vout = fh; u16 multiplier = 1; - u8 device_type = PROGRESSIVE; - /* default is progressive buffer and progressive display */ - enum device_n_buffer_type dev_buf_type = PBUF_PDEV; + bool interlace = false; + enum device_n_buffer_type dev_buf_type; if (vout->streaming) return -EBUSY; @@ -1912,25 +1891,53 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, /* validate the combination of input buffer & device type. Code needs to be added for interlaced LCD display */ if (ovl->manager->device->type == OMAP_DISPLAY_TYPE_HDMI) - device_type = nature_of_hdmi(); + interlace = is_hdmi_interlaced(); - if (f->fmt.pix.field != V4L2_FIELD_NONE && - f->fmt.pix.field != V4L2_FIELD_SEQ_TB) + switch (f->fmt.pix.field) { + case V4L2_FIELD_ANY: + /* default to no interlacing */ f->fmt.pix.field = V4L2_FIELD_NONE; - if ((f->fmt.pix.field == V4L2_FIELD_NONE) && - (device_type == PROGRESSIVE)) - dev_buf_type = PBUF_PDEV; - else if ((f->fmt.pix.field == V4L2_FIELD_NONE) && - (device_type == INTERLACED)) - dev_buf_type = PBUF_IDEV; - else if ((f->fmt.pix.field == V4L2_FIELD_SEQ_TB) && - (device_type == INTERLACED)) - dev_buf_type = IBUF_IDEV; - else if ((f->fmt.pix.field == V4L2_FIELD_SEQ_TB) && - (device_type == PROGRESSIVE)) - dev_buf_type = IBUF_PDEV; + /* fall through to V4L2_FIELD_NONE */ + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + /* These are really non-interlaced, so treat as FIELD_NONE */ + + case V4L2_FIELD_NONE: + /* Treat progressive images as TB interleaved */ + + case V4L2_FIELD_INTERLACED: + case V4L2_FIELD_INTERLACED_TB: + /* + * We don't provide deinterlacing, so simply display these + * on progressive displays + */ + dev_buf_type = interlace ? PBUF_IDEV : PBUF_PDEV; + break; + + case V4L2_FIELD_INTERLACED_BT: + /* switch fields for interlaced buffers. We cannot display + these on progressive display */ + if (!interlace) + return -EINVAL; + dev_buf_type = PBUF_IDEV_SWAP; + break; + + case V4L2_FIELD_SEQ_TB: + dev_buf_type = interlace ? IBUF_IDEV : IBUF_PDEV; + break; + + case V4L2_FIELD_SEQ_BT: + dev_buf_type = interlace ? IBUF_IDEV_SWAP : IBUF_PDEV_SWAP; + break; + case V4L2_FIELD_ALTERNATE: + /* no support for this format */ + default: + return -EINVAL; + } + + /* TODO: check if TILER ADAPTATION is needed here. */ /* We dont support RGB24-packed mode if vrfb rotation * is enabled*/ if ((rotation_enabled(vout)) && @@ -1939,11 +1946,11 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, goto s_fmt_vid_out_exit; } - /* y resolution to be doubled in case of interlaced HDMI */ - if ((ovl->info.field == IBUF_IDEV) || (ovl->info.field == PBUF_IDEV)) + /* get the framebuffer parameters */ + /* y resolution to be doubled in case of interlaced output */ + if (dev_buf_type & OMAP_FLAG_IDEV) multiplier = 2; - /* get the framebuffer parameters */ if (!cpu_is_omap44xx() && rotate_90_or_270(vout)) { vout->fbuf.fmt.height = timing->x_res; vout->fbuf.fmt.width = timing->y_res * multiplier; @@ -1966,7 +1973,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, vout->pix = f->fmt.pix; vout->vrfb_bpp = 1; ovl->info.field = dev_buf_type; - ovl->info.pic_width = f->fmt.pix.width; ovl->info.pic_height = f->fmt.pix.height; /* If YUYV then vrfb bpp is 2, for others its 1 */ @@ -2174,8 +2180,8 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) /* get the display device attached to the overlay */ timing = &ovl->manager->device->panel.timings; - /* y resolution to be doubled in case of interlaced HDMI */ - if ((ovl->info.field == IBUF_IDEV) || (ovl->info.field == PBUF_IDEV)) + /* y resolution to be doubled in case of interlaced output */ + if (ovl->info.field & OMAP_FLAG_IDEV) multiplier = 2; if (rotate_90_or_270(vout)) { diff --git a/drivers/media/video/omap/omap_wb.c b/drivers/media/video/omap/omap_wb.c index ca7480de0de1..03f19bf82c39 100644 --- a/drivers/media/video/omap/omap_wb.c +++ b/drivers/media/video/omap/omap_wb.c @@ -606,6 +606,16 @@ static int omap_wb_tiler_buffer_setup(struct omap_wb_device *wb, (void **) wb->buf_phy_uv_addr_alloced + start, aligned); } else { + unsigned int width = pix->width; + switch (video_mode_to_dss_mode(pix)) { + case OMAP_DSS_COLOR_UYVY: + case OMAP_DSS_COLOR_YUV2: + width /= 2; + bpp = 4; + break; + default: + break; + } /* Only bpp of 1, 2, and 4 is supported by tiler */ fmt = (bpp == 1 ? TILFMT_8BIT : bpp == 2 ? TILFMT_16BIT : @@ -613,7 +623,7 @@ static int omap_wb_tiler_buffer_setup(struct omap_wb_device *wb, if (fmt == TILFMT_INVALID) return -ENOMEM; - tiler_alloc_packed(&n_alloc, fmt, pix->width, + tiler_alloc_packed(&n_alloc, fmt, width, pix->height, (void **) wb->buf_phy_addr + start, (void **) wb->buf_phy_addr_alloced + start, diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 2b23c75aa551..1eab132328b1 100755..100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -147,6 +147,7 @@ static void core_dump_clocks(struct seq_file *s) seq_printf(s, "- CORE -\n"); seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); + seq_printf(s, "mainclk count\t\t%u\n", dss_get_mainclk_state()); for (i = 0; i < 5; i++) { if (!clocks[i]) @@ -302,6 +303,7 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks) { unsigned num_clks = count_clk_bits(clks); + /* don't do aggressive clock cutting on OMAP4 */ if (cpu_is_omap44xx()) return; @@ -328,11 +330,21 @@ void dss_clk_enable(enum dss_clock clks) if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) restore_all_ctx(); } -void dss_opt_clock_enable() + +int dss_opt_clock_enable() { - clk_enable(core.dss_ick); - clk_enable(core.dss1_fck); - clk_enable(core.dss_96m_fck); + int r = clk_enable(core.dss_ick); + if (!r) { + r = clk_enable(core.dss1_fck); + if (!r) { + r = clk_enable(core.dss_96m_fck); + if (!r) + return 0; + clk_disable(core.dss1_fck); + } + clk_disable(core.dss_ick); + } + return r; } void dss_opt_clock_disable() @@ -472,8 +484,10 @@ struct regulator *dss_get_vdda_dac(void) static void dss_debug_dump_clocks(struct seq_file *s) { core_dump_clocks(s); - dss_dump_clocks(s); - dispc_dump_clocks(s); + if (dss_get_mainclk_state()) { + dss_dump_clocks(s); + dispc_dump_clocks(s); + } #ifdef CONFIG_OMAP2_DSS_DSI dsi1_dump_clocks(s); dsi2_dump_clocks(s); diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 0ab488f219f3..a53b509ccacb 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -202,13 +202,13 @@ void __iomem *dispc_base; /* n=0: VID3, n=1: WB*/ /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} n=0: VID3, n=1: WB */ -#define DISPC_VID_V3_WB_FIR_COEF_H2(n, i) DISPC_REG(0x0730+(n)*0x6C+(i)*0x8) +#define DISPC_VID_V3_WB_FIR_COEF_H2(n, i) DISPC_REG(0x0730+(n)*0x70+(i)*0x8) /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -#define DISPC_VID_V3_WB_FIR_COEF_HV2(n, i) DISPC_REG(0x0734+(n)*0x6C+(i)*0x8) +#define DISPC_VID_V3_WB_FIR_COEF_HV2(n, i) DISPC_REG(0x0734+(n)*0x70+(i)*0x8) /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -#define DISPC_VID_V3_WB_FIR_COEF_V2(n, i) DISPC_REG(0x0770+(n)*0x6C+(i)*0x4) +#define DISPC_VID_V3_WB_FIR_COEF_V2(n, i) DISPC_REG(0x0770+(n)*0x70+(i)*0x4) /*********End Vid3 and WB Registers ***************/ @@ -1246,7 +1246,7 @@ static void _dispc_set_scale_coef(enum omap_plane plane, const s8 *hfir, ((vfir[16] << 16) & 0xFF0000) | ((vfir[24] << 24) & 0xFF000000)); v = ((vfir[0] & 0xFF) | ((vfir[32] << 8) & 0xFF00)); - + _dispc_write_firh_reg(plane, i, h); _dispc_write_firhv_reg(plane, i, hv); _dispc_write_firv_reg(plane, i, v); @@ -1842,7 +1842,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) { u32 val; - struct dispc_reg ac1_reg[4] = { DISPC_VID_ACCU1(0), + struct dispc_reg ac1_reg[4] = { DISPC_VID_ACCU1(0), DISPC_VID_ACCU1(1) }; if (cpu_is_omap44xx()){ @@ -2071,24 +2071,24 @@ static void _dispc_set_scaling(enum omap_plane plane, BUG_ON(plane == OMAP_DSS_GFX); if (scale_x) { - fir_hinc = 1024 * (orig_width - 1) / (out_width - 1); + fir_hinc = (1024 * orig_width) / out_width; if (fir_hinc > 4095) fir_hinc = 4095; hfir = get_scaling_coef(orig_width, out_width, 0, 0, 0); } else { - fir_hinc = 0; - hfir = fir5_zero; + fir_hinc = 1024; + hfir = fir3_m8; } if (scale_y) { - fir_vinc = 1024 * (orig_height - 1) / (out_height - 1); + fir_vinc = (1024 * orig_height) / out_height; if (fir_vinc > 4095) fir_vinc = 4095; vfir = get_scaling_coef(orig_height, out_height, 0, 0, three_taps); - } else { - fir_vinc = 0; - vfir = fir5_zero; + } else { + fir_vinc = 1024; + vfir = fir3_m8; } _dispc_set_scale_coef(plane, hfir, vfir, three_taps); @@ -2138,24 +2138,24 @@ static void _dispc_set_scaling_uv(enum omap_plane plane, const s8 *hfir, *vfir; if (scale_x) { - fir_hinc = 1024 * (orig_width - 1) / (out_width - 1); + fir_hinc = (1024 * orig_width) / out_width; if (fir_hinc > 4095) fir_hinc = 4095; hfir = get_scaling_coef(orig_width, out_width, 0, 0, 0); } else { - fir_hinc = 0; - hfir = fir5_zero; + fir_hinc = 1024; + hfir = fir3_m8; } if (scale_y) { - fir_vinc = 1024 * (orig_height - 1) / (out_height - 1); + fir_vinc = (1024 * orig_height) / out_height; if (fir_vinc > 4095) fir_vinc = 4095; vfir = get_scaling_coef(orig_height, out_height, 0, ilace, three_taps); } else { - fir_vinc = 0; - vfir = fir5_zero; + fir_vinc = 1024; + vfir = fir3_m8; } for (i = 0; i < 8; i++, hfir++, vfir++) { @@ -2174,25 +2174,30 @@ static void _dispc_set_scaling_uv(enum omap_plane plane, if (three_taps && v) printk(KERN_ERR "three_tap v is %x\n", v); } - - /* set chroma resampling */ - REG_FLD_MOD(DISPC_VID_ATTRIBUTES2(plane - 1), - (fir_hinc || fir_vinc) ? 1 : 0, 8, 8); + /* set chroma resampling. Not applicable for WB plane*/ + if (plane != OMAP_DSS_WB) + REG_FLD_MOD(DISPC_VID_ATTRIBUTES2(plane - 1), + (fir_hinc || fir_vinc) ? 1 : 0, 8, 8); /* set H scaling */ - REG_FLD_MOD(dispc_reg_att[plane], fir_hinc ? 1 : 0, 6, 6); + REG_FLD_MOD(dispc_reg_att[plane], fir_hinc ? 1 : 0, 5, 5); /* set V scaling */ - REG_FLD_MOD(dispc_reg_att[plane], fir_vinc ? 1 : 0, 5, 5); + REG_FLD_MOD(dispc_reg_att[plane], fir_vinc ? 1 : 0, 6, 6); _dispc_set_fir2(plane, fir_hinc, fir_vinc); - if (ilace == IBUF_IDEV) { + if ((ilace & OMAP_FLAG_IBUF) && + (ilace & OMAP_FLAG_IDEV)) { accu0 = (-3 * fir_vinc / 4) % 1024; accu1 = (-fir_vinc / 4) % 1024; } else { accu0 = accu1 = (-fir_vinc / 2) % 1024; } + + if (ilace & OMAP_FLAG_ISWAP) + swap(accu0, accu1); + accuh = (-fir_hinc / 2) % 1024; _dispc_set_vid_accu2_0(plane, 0x80, 0); @@ -2204,55 +2209,59 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, bool mirroring, enum omap_color_mode color_mode) { BUG_ON(plane == OMAP_DSS_WB); - if (!cpu_is_omap44xx()) { - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) { - int vidrot = 0; - - if (mirroring) { - switch (rotation) { - case OMAP_DSS_ROT_0: - vidrot = 2; - break; - case OMAP_DSS_ROT_90: - vidrot = 1; - break; - case OMAP_DSS_ROT_180: - vidrot = 0; - break; - case OMAP_DSS_ROT_270: - vidrot = 3; - break; - } - } else { - switch (rotation) { - case OMAP_DSS_ROT_0: - vidrot = 0; - break; - case OMAP_DSS_ROT_90: - vidrot = 1; - break; - case OMAP_DSS_ROT_180: - vidrot = 2; - break; - case OMAP_DSS_ROT_270: - vidrot = 3; - break; - } + + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) { + int vidrot = 0; + + if (mirroring) { + switch (rotation) { + case OMAP_DSS_ROT_0: + vidrot = 2; + break; + case OMAP_DSS_ROT_90: + vidrot = 1; + break; + case OMAP_DSS_ROT_180: + vidrot = 0; + break; + case OMAP_DSS_ROT_270: + vidrot = 3; + break; } + } else { + switch (rotation) { + case OMAP_DSS_ROT_0: + vidrot = 0; + break; + case OMAP_DSS_ROT_90: + vidrot = 1; + break; + case OMAP_DSS_ROT_180: + vidrot = 2; + break; + case OMAP_DSS_ROT_270: + vidrot = 3; + break; + } + } - REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); + REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); + if (!cpu_is_omap44xx()) { if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); else REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); - } else { - REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); - REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); } - } else if (plane != OMAP_DSS_GFX) { + } else { + REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); + if (!cpu_is_omap44xx()) + REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); + } + + if (plane != OMAP_DSS_GFX) { if (color_mode == OMAP_DSS_COLOR_NV12) { /* DOUBLESTRIDE : 0 for 90-, 270-; 1 for 0- and 180- */ if (rotation == 1 || rotation == 3) @@ -2260,12 +2269,6 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, else REG_FLD_MOD(dispc_reg_att[plane], 0x1, 22, 22); } - /* Set the rotation value for pipeline */ - if (color_mode == OMAP_DSS_COLOR_UYVY || - color_mode == OMAP_DSS_COLOR_YUV2) - REG_FLD_MOD(dispc_reg_att[plane], rotation, 13, 12); - else - REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); } } @@ -2311,19 +2314,18 @@ static s32 pixinc(int pixels, u8 ps) BUG(); } -void calc_tiler_row_rotation(u8 rotation, +static void calc_tiler_row_rotation(u8 rotation, u16 width, enum omap_color_mode color_mode, int y_decim, s32 *row_inc, unsigned *offset1, enum device_n_buffer_type ilace, - u16 pic_width, u16 pic_height) { u8 ps = 1; u32 line_size = 0; - DSSDBG("calc_tiler_rot(%d): %d\n", rotation, width); + DSSDBG("calc_tiler_rot(%d): %dx%d\n", rotation, width, pic_height); switch (color_mode) { case OMAP_DSS_COLOR_RGB16: @@ -2360,6 +2362,7 @@ void calc_tiler_row_rotation(u8 rotation, case 1: case 3: + /* input width/height already swapped for rotated frames */ line_size = (4 == ps) ? 16384 : 8192 ; break; @@ -2368,21 +2371,28 @@ void calc_tiler_row_rotation(u8 rotation, return; } - *row_inc = line_size * y_decim + 1 - (width * ps) + - ((ilace == PBUF_IDEV) ? (line_size * y_decim) : 0); + /* assume TB. We worry about swapping top/bottom outside of this call */ - if ((ilace == IBUF_IDEV) || (ilace == IBUF_PDEV)) + if (ilace & OMAP_FLAG_IBUF) { + /* bottom half of image is the odd frame */ *offset1 = line_size * pic_height; - else if (ilace == PBUF_IDEV) - *offset1 = line_size; + } else if (ilace & OMAP_FLAG_IDEV) { + /* even and odd frames are interleaved */ + + /* offset1 is always at an odd line */ + *offset1 = line_size * (y_decim | 1); + y_decim *= 2; + } + *row_inc = line_size * y_decim + 1 - (width * ps); DSSDBG(" colormode: %d, rotation: %d, ps: %d, width: %d," - " row_inc:%d\n", - color_mode, rotation, ps, width, *row_inc); + " height: %d, row_inc:%d\n", + color_mode, rotation, ps, width, pic_height, *row_inc); return; } + static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, u16 screen_width, u16 width, u16 height, @@ -2702,9 +2712,10 @@ int dispc_scaling_decision(u16 width, u16 height, bool can_scale = plane != OMAP_DSS_GFX; u16 in_width, in_height; - unsigned long fclk = 0; + unsigned long fclk = 0, fclk5 = 0; int min_factor, max_factor; /* decimation search limits */ int x, y; /* decimation search variables */ + unsigned long fclk_max = dispc_fclk_rate(); /* restrict search region based on whether we can decimate */ if (!can_decimate_x) { @@ -2720,9 +2731,6 @@ int dispc_scaling_decision(u16 width, u16 height, if (min_y_decim > 1) return -EINVAL; min_y_decim = max_y_decim = 1; - } else { - if (max_y_decim > 16) - max_y_decim = 16; } /* @@ -2757,8 +2765,8 @@ int dispc_scaling_decision(u16 width, u16 height, y < min_y_decim || y > max_y_decim) goto loop; - in_width = width / x; - in_height = height / y; + in_width = DIV_ROUND_UP(width, x); + in_height = DIV_ROUND_UP(height, y); if (in_width == out_width && in_height == out_height) break; @@ -2771,53 +2779,56 @@ int dispc_scaling_decision(u16 width, u16 height, goto loop; /* Must use 3-tap filter */ + *three_tap = false; if (!cpu_is_omap44xx()) *three_tap = in_width > 1024; else if (omap_rev() == OMAP4430_REV_ES1_0) *three_tap = in_width > 1280; - else - /* use 3-tap unless downscaling by more than 2 */ - *three_tap = out_height * 2 >= in_height; - - /* predecimation on OMAP4 still fetches the whole lines, so - we multiply back the width (still closer than using width) */ - if (*three_tap) { - fclk = calc_fclk(channel, in_width, - in_height, out_width, out_height); - - /* Try 5-tap filter if 3-tap fclk is too high*/ - if (cpu_is_omap34xx() && in_height > out_height && - fclk > dispc_fclk_rate()) { - printk(KERN_ERR - "Should use 5 tap but cannot\n"); - } - } else { - fclk = calc_fclk_five_taps(channel, - in_width, in_height, - out_width, out_height, color_mode); - } + /* Also use 3-tap if downscaling by 2 or less */ + *three_tap |= out_height * 2 >= in_height; + + /* + * Predecimation on OMAP4 still fetches the whole lines + * :TODO: How does it affect the required clock speed? + */ + fclk = calc_fclk(channel, in_width, in_height, + out_width, out_height); + fclk5 = *three_tap ? 0 : + calc_fclk_five_taps(channel, in_width, in_height, + out_width, out_height, color_mode); + + DSSDBG("%d*%d,%d*%d->%d,%d requires %lu(3T), %lu(5T) Hz\n", + in_width, x, in_height, y, out_width, out_height, + fclk, fclk5); + + /* Use 3-tap if 5-tap clock requirement is too high */ + *three_tap |= fclk5 > fclk_max; + + /* for now we always use 5-tap unless 3-tap is required */ + if (!*three_tap) + fclk = fclk5; /* OMAP2/3 has a scaler size limitation */ if (!cpu_is_omap44xx() && in_width > (1024 << *three_tap)) goto loop; DSSDBG("required fclk rate = %lu Hz\n", fclk); - DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); + DSSDBG("current fclk rate = %lu Hz\n", fclk_max); - if (fclk > dispc_fclk_rate()) { - DSSERR("failed to set up scaling, " - "required fclk rate = %lu Hz, " - "current fclk rate = %lu Hz\n", - fclk, dispc_fclk_rate()); + if (fclk > fclk_max) goto loop; - } break; loop: /* err if exhausted search region */ - if (x == max_x_decim && y == max_y_decim) + if (x == max_x_decim && y == max_y_decim) { + DSSERR("failed to set up scaling, " + "required fclk rate = %lu Hz, " + "current fclk rate = %lu Hz\n", + fclk, fclk_max); return -EINVAL; + } /* get to next factor */ if (x == y) { @@ -2847,7 +2858,7 @@ static int _dispc_setup_plane(enum omap_plane plane, u8 rotation, int mirror, u8 global_alpha, enum omap_channel channel, u32 puv_addr, - u16 pic_width, u16 pic_height) + u16 pic_height) { bool fieldmode = 0; int cconv = 0; @@ -2862,20 +2873,22 @@ static int _dispc_setup_plane(enum omap_plane plane, if (paddr == 0) return -EINVAL; + /* NOTE: fieldmode is not used on OMAP4 -> neither for predecimation */ if (ilace && height == out_height) fieldmode = 1; - if ((ilace == IBUF_IDEV) || (ilace == IBUF_PDEV) || - (ilace == PBUF_IDEV)) { + if (ilace != PBUF_PDEV) { #ifdef CONFIG_OMAP2_DSS_HDMI + /* HDMI output */ height /= 2; #else + /* VENC output */ if (fieldmode) height /= 2; #endif pos_y /= 2; pic_height /= 2; - if ((ilace == IBUF_IDEV) || (ilace == PBUF_IDEV)) + if (ilace & OMAP_FLAG_IDEV) out_height /= 2; DSSDBG("adjusting for ilace: height %d, pos_y %d, " @@ -2883,6 +2896,7 @@ static int _dispc_setup_plane(enum omap_plane plane, height, pos_y, out_height); } + /* check if color format is supported */ if (plane == OMAP_DSS_GFX) { switch (color_mode) { case OMAP_DSS_COLOR_ARGB16: @@ -2942,8 +2956,8 @@ static int _dispc_setup_plane(enum omap_plane plane, } /* predecimate */ - width /= x_decim; - height /= y_decim; + width = DIV_ROUND_UP(width, x_decim); + height = DIV_ROUND_UP(height, y_decim); if (ilace && !fieldmode) { /* @@ -2962,83 +2976,85 @@ static int _dispc_setup_plane(enum omap_plane plane, /* Fields are independent but interleaved in memory. */ if (fieldmode) field_offset = 1; - pix_inc = 0x1; - offset0 = 0x0; - offset1 = 0x0; - if(cpu_is_omap44xx()) { - /* check if tiler address; else set row_inc = 1*/ - if ((paddr >= 0x60000000) && (paddr <= 0x7fffffff)) { - struct tiler_view_orient orient; - u8 mir_x = 0, mir_y = 0; - unsigned long tiler_width, tiler_height; - - pix_inc = 1 + (x_decim - 1) * bpp; - calc_tiler_row_rotation(rotation, width * x_decim, - color_mode, y_decim, &row_inc, &offset1, - ilace, pic_width, pic_height); - - /* get rotated top-left coordinate - (if rotation is applied before mirroring) */ - memset(&orient, 0, sizeof(orient)); + /* default values */ + row_inc = pix_inc = 0x1; + offset0 = offset1 = 0x0; + + if (rotation_type == OMAP_DSS_ROT_TILER) { + struct tiler_view_orient orient = {0}; + unsigned long tiler_width = width, tiler_height = height; + u8 mir_x = 0, mir_y = 0; + u8 tiler_rotation = rotation; + + pix_inc = 1 + (x_decim - 1) * bpp; + calc_tiler_row_rotation(rotation, width * x_decim, + color_mode, y_decim, &row_inc, + &offset1, ilace, pic_height); + + if (ilace & OMAP_FLAG_ISWAP) + swap(offset0, offset1); + + /* mirroring is applied before rotataion */ + if (tiler_rotation & 1) + tiler_rotation ^= 2; + + tiler_rotate_view(&orient, tiler_rotation * 90); + + if (mirror) { if (rotation & 1) - rotation ^= 2; + mir_x = 1; + else + mir_y = 1; + } + orient.x_invert ^= mir_x; + orient.y_invert ^= mir_y; - tiler_rotate_view(&orient, rotation * 90); + DSSDBG("RXY = %d %d %d\n", orient.rotate_90, + orient.x_invert, orient.y_invert); - if (mirror) { - if (rotation & 1) - mir_x = 1; - else - mir_y = 1; - } - orient.x_invert ^= mir_x; - orient.y_invert ^= mir_y; - - DSSDBG("RXY = %d %d %d\n", orient.rotate_90, - orient.x_invert, orient.y_invert); - - if (orient.rotate_90 & 1) { - tiler_height = width; - tiler_width = height; - } else { - tiler_height = height; - tiler_width = width; - } + if (orient.rotate_90 & 1) + swap(tiler_width, tiler_height); - switch (color_mode) { - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: - tiler_width /= 2; - break; - default: - break; - } - DSSDBG("w, h = %ld %ld\n", tiler_width, tiler_height); + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + tiler_width /= 2; - paddr = tiler_reorient_topleft(tiler_get_natural_addr((void *)paddr), + DSSDBG("w, h = %ld %ld\n", tiler_width, tiler_height); + + paddr = tiler_reorient_topleft( + tiler_get_natural_addr((void *)paddr), orient, tiler_width, tiler_height); + if (puv_addr) + puv_addr = tiler_reorient_topleft( + tiler_get_natural_addr( + (void *) puv_addr), orient, + tiler_width/2, tiler_height/2); + + /* + * BA1 used as temporary storage to pointer to lower + * half of interlaced buffer on progressive display + */ + if ((ilace & OMAP_FLAG_IBUF) && !(ilace & OMAP_FLAG_IDEV)) { + dispc_write_reg(DISPC_VID_BA1(plane - 1), + paddr + offset1); + /* UV offset is 1/2 Y offset for even offsets */ if (puv_addr) - puv_addr = tiler_reorient_topleft( - tiler_get_natural_addr((void *)puv_addr), - orient, tiler_width/2, tiler_height/2); - DSSDBG("rotated addresses: 0x%0x, 0x%0x\n", + dispc_write_reg(DISPC_VID_BA_UV1(plane - 1), + puv_addr + offset1 / 2); + } + DSSDBG("rotated addresses: 0x%0x, 0x%0x\n", paddr, puv_addr); - /* set BURSTTYPE if rotation is non-zero */ - REG_FLD_MOD(dispc_reg_att[plane], 0x1, 29, 29); - } else - row_inc = 0x1; - } - if (!cpu_is_omap44xx()) { - row_inc = 0x1; - if (rotation_type == OMAP_DSS_ROT_DMA) - calc_dma_rotation_offset(rotation, mirror, + /* set BURSTTYPE if rotation is non-zero */ + REG_FLD_MOD(dispc_reg_att[plane], 0x1, 29, 29); + } else if (rotation_type == OMAP_DSS_ROT_DMA) { + calc_dma_rotation_offset(rotation, mirror, screen_width, width, frame_height, color_mode, fieldmode, field_offset, &offset0, &offset1, &row_inc, &pix_inc); - else - calc_vrfb_rotation_offset(rotation, mirror, + } else if (rotation_type == OMAP_DSS_ROT_VRFB) { + calc_vrfb_rotation_offset(rotation, mirror, screen_width, width, frame_height, color_mode, fieldmode, field_offset, &offset0, &offset1, &row_inc, &pix_inc); @@ -3959,6 +3975,70 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_VID_SIZE(1)); DUMPREG(DISPC_VID_ATTRIBUTES(1)); DUMPREG(DISPC_VID_V3_WB_ATTRIBUTES(1)); + DUMPREG(DISPC_VID_V3_WB_ACCU0(1)); + DUMPREG(DISPC_VID_V3_WB_ACCU1(1)); + DUMPREG(DISPC_VID_V3_WB_BA0(1)); + DUMPREG(DISPC_VID_V3_WB_BA1(1)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 0)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 1)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 2)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 3)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 4)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 5)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 6)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H(1, 7)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 0)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 1)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 2)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 3)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 4)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 5)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 6)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV(1, 7)); + + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 0)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 1)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 2)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 3)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 4)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 5)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 6)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_H2(1, 7)); + + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 0)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 1)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 2)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 3)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 4)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 5)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 6)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_HV2(1, 7)); + + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 0)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 1)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 2)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 3)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 4)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 5)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 6)); + DUMPREG(DISPC_VID_V3_WB_FIR_COEF_V2(1, 7)); + + DUMPREG(DISPC_VID_V3_WB_BUF_SIZE_STATUS(1)); + DUMPREG(DISPC_VID_V3_WB_BUF_THRESHOLD(1)); + DUMPREG(DISPC_VID_V3_WB_FIR(1)); + DUMPREG(DISPC_VID_V3_WB_PICTURE_SIZE(1)); + DUMPREG(DISPC_VID_V3_WB_PIXEL_INC(1)); + DUMPREG(DISPC_VID_V3_WB_ROW_INC(1)); + DUMPREG(DISPC_VID_V3_WB_SIZE(1)); + DUMPREG(DISPC_VID_V3_WB_FIR2(1)); + DUMPREG(DISPC_VID_V3_WB_ACCU2_0(1)); + DUMPREG(DISPC_VID_V3_WB_ACCU2_1(1)); + DUMPREG(DISPC_VID_V3_WB_CONV_COEF(1, 0)); + DUMPREG(DISPC_VID_V3_WB_CONV_COEF(1, 1)); + DUMPREG(DISPC_VID_V3_WB_CONV_COEF(1, 2)); + DUMPREG(DISPC_VID_V3_WB_CONV_COEF(1, 3)); + DUMPREG(DISPC_VID_V3_WB_CONV_COEF(1, 4)); + DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); DUMPREG(DISPC_VID_ROW_INC(1)); @@ -4579,7 +4659,6 @@ static void dispc_error_worker(struct work_struct *work) if (enable) dssdev->driver->enable(dssdev); } - } if (errors & DISPC_IRQ_OCP_ERR) { @@ -4678,7 +4757,7 @@ void dispc_fake_vsync_irq(enum omap_dsi_index ix) DSSERR("Invalid display id for fake vsync\n"); return; } - + for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { struct omap_dispc_isr_data *isr_data; isr_data = &dispc.registered_isr[i]; @@ -4808,24 +4887,24 @@ int dispc_enable_plane(enum omap_plane plane, bool enable) } int dispc_setup_plane(enum omap_plane plane, - u32 paddr, u16 screen_width, - u16 pos_x, u16 pos_y, - u16 width, u16 height, - u16 out_width, u16 out_height, - enum omap_color_mode color_mode, - enum device_n_buffer_type ilace, - int x_decim, int y_decim, bool three_tap, - enum omap_dss_rotation_type rotation_type, - u8 rotation, bool mirror, u8 global_alpha, - enum omap_channel channel, u32 puv_addr, - u16 pic_width, u16 pic_height) + u32 paddr, u16 screen_width, + u16 pos_x, u16 pos_y, + u16 width, u16 height, + u16 out_width, u16 out_height, + enum omap_color_mode color_mode, + enum device_n_buffer_type ilace, + int x_decim, int y_decim, bool three_tap, + enum omap_dss_rotation_type rotation_type, + u8 rotation, bool mirror, u8 global_alpha, + enum omap_channel channel, u32 puv_addr, + u16 pic_height) { int r = 0; DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> %dx%d, " - "ilace %d, decim %dx%d, %d-tap, cmode %x, rot %d, mir %d " - "chan %d\n", + "ilace %d, decim %dx%d, %d-tap, cmode %x, rot %d, mir %d " + "chan %d\n", plane, paddr, screen_width, pos_x, pos_y, width, height, out_width, out_height, @@ -4844,33 +4923,33 @@ int dispc_setup_plane(enum omap_plane plane, rotation, mirror, global_alpha, channel, puv_addr, - pic_width, pic_height); + pic_height); enable_clocks(0); return r; } -void change_base_address(u32 offset, u16 *flag, int id) +/* retrives the new adress from BA1 and puts it into BA0 */ +void change_base_address(int plane, u32 p_uv_addr) + { - u32 val; - if (*flag == 0) { - val = dispc_read_reg(DISPC_VID_BA0(id - 1)); - dispc_write_reg(DISPC_VID_BA0(id - 1), val+offset); - val = dispc_read_reg(DISPC_VID_BA_UV0(id - 1)); - dispc_write_reg(DISPC_VID_BA_UV0(id - 1), val+offset); - *flag = *flag + 1; - } + u32 val; + val = dispc_read_reg(DISPC_VID_BA1(plane - 1)); + dispc_write_reg(DISPC_VID_BA0(plane - 1), val); + if (p_uv_addr) { + val = dispc_read_reg(DISPC_VID_BA_UV1(plane - 1)); + dispc_write_reg(DISPC_VID_BA_UV0(plane - 1), val); + } } /* Writeback*/ int dispc_setup_wb(struct writeback_cache_data *wb) { - unsigned long mir_x, mir_y; unsigned long tiler_width, tiler_height; - u8 orientation = 0, rotation = 0, mirror = 0 ; + u8 rotation = 0, mirror = 0 ; int ch_width, ch_height, out_ch_width, out_ch_height, scale_x, scale_y; - struct tiler_view_orient orient; + struct tiler_view_orient orient = {0}; u32 paddr = wb->paddr; u32 puv_addr = wb->puv_addr; /* relevant for NV12 format only */ u16 out_width = wb->width; @@ -4880,7 +4959,7 @@ int dispc_setup_wb(struct writeback_cache_data *wb) unsigned offset1 = 0; enum device_n_buffer_type ilace = PBUF_PDEV; - u16 pic_width = 0, pic_height = 0;/* not required in case + u16 pic_height = 0;/* not required in case of progressive cases */ enum omap_color_mode color_mode = wb->color_mode; /* output color */ @@ -4981,38 +5060,37 @@ int dispc_setup_wb(struct writeback_cache_data *wb) pix_inc = 0x1; if ((paddr >= 0x60000000) && (paddr <= 0x7fffffff)) { + u8 mir_x = 0, mir_y = 0; + tiler_width = out_width, tiler_height = out_height; + calc_tiler_row_rotation(rotation, out_width, color_mode, 1, /* y_decim = 1 */ &row_inc, &offset1, ilace, - pic_width, pic_height); + pic_height); + + /* mirroring is applied before rotataion */ + /* mirroring is applied before rotataion */ + if (rotation & 1) + rotation ^= 2; - orientation = calc_tiler_orientation(rotation, (u8)mirror); - /* get rotated top-left coordinate - (if rotation is applied before mirroring) */ - memset(&orient, 0, sizeof(orient)); tiler_rotate_view(&orient, rotation * 90); if (mirror) { - /* Horizontal mirroring */ - if (rotation == 1 || rotation == 3) + if (rotation & 1) mir_x = 1; else mir_y = 1; - } else { - mir_x = 0; - mir_y = 0; } orient.x_invert ^= mir_x; orient.y_invert ^= mir_y; - if (orient.rotate_90 & 1) { - tiler_height = width; - tiler_width = height; - } else { - tiler_height = height; - tiler_width = width; - } + if (orient.rotate_90 & 1) + swap(tiler_width, tiler_height); + + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + tiler_width /= 2; paddr = tiler_reorient_topleft(tiler_get_natural_addr((void *)paddr), orient, tiler_width, tiler_height); @@ -5021,10 +5099,11 @@ int dispc_setup_wb(struct writeback_cache_data *wb) puv_addr = tiler_reorient_topleft( tiler_get_natural_addr((void *)puv_addr), orient, tiler_width/2, tiler_height/2); - DSSDBG("rotated addresses: 0x%0x, 0x%0x\n", + + DSSDBG("rotated addresses: 0x%0x, 0x%0x\n", paddr, puv_addr); - /* set BURSTTYPE if rotation is non-zero */ - REG_FLD_MOD(dispc_reg_att[plane], 0x1, 8, 8); + /* set BURSTTYPE if rotation is non-zero */ + REG_FLD_MOD(dispc_reg_att[plane], 0x1, 8, 8); } else row_inc = 1; @@ -5036,6 +5115,12 @@ int dispc_setup_wb(struct writeback_cache_data *wb) if (OMAP_DSS_COLOR_NV12 == color_mode) { _dispc_set_plane_ba_uv0(plane, puv_addr); _dispc_set_plane_ba_uv1(plane, puv_addr); + + /* DOUBLESTRIDE : 0 for 90-, 270-; 1 for 0- and 180- */ + if (rotation == 1 || rotation == 3) + REG_FLD_MOD(dispc_reg_att[plane], 0x0, 22, 22); + else + REG_FLD_MOD(dispc_reg_att[plane], 0x1, 22, 22); } _dispc_set_row_inc(plane, row_inc); _dispc_set_pix_inc(plane, pix_inc); @@ -5080,9 +5165,9 @@ int dispc_setup_wb(struct writeback_cache_data *wb) out_width, out_height, 0, three_taps, false, scale_x, scale_y); - if (ch_width != width) { + if (out_ch_width != out_width) { /* this is true for YUV formats */ - printk(KERN_ERR "scale uv set"); + DSSDBG("scale uv set"); _dispc_set_scaling_uv(plane, ch_width, ch_height, out_ch_width, out_ch_height, 0, three_taps, false, scale_x, scale_y); diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index aa6dc7578abf..d2b0b690194d 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -601,8 +601,12 @@ static int dss_resume_device(struct device *dev, void *data) if (dssdev->activate_after_resume && dssdev->driver->resume) { r = dssdev->driver->resume(dssdev); - if (r) + if (r) { + DSSERR("Failed to resume %s device (%d), disabling\n", + dssdev->name, r); + dssdev->driver->disable(dssdev); return r; + } } dssdev->activate_after_resume = false; @@ -628,7 +632,10 @@ static int dss_check_state_disabled(struct device *dev, void *data) return -EINVAL; } -/* disables mainclk if all devices are suspended /disabled */ +/* + * Checks if all devices are suspended/disabled. + * Disables mainclk (DSS clocks on OMAP4) if true and do_clk_disable is true. + */ int dss_mainclk_state_disable(bool do_clk_disable) { int r; @@ -637,8 +644,8 @@ int dss_mainclk_state_disable(bool do_clk_disable) r = bus_for_each_dev(bus, NULL, NULL, dss_check_state_disabled); if (r) { - /* All devices are not disabled /suspended */ - return -EINVAL; + /* Some devices are not disabled/suspended */ + return -EBUSY; } else { if (do_clk_disable) { save_all_ctx(); @@ -648,7 +655,11 @@ int dss_mainclk_state_disable(bool do_clk_disable) } } -/* enables mainclk if all devices are suspended /disabled */ +/* + * enables mainclk (DSS clocks on OMAP4 if all devices are either in disabled or + * suspended state before calling this function. + * Returns 0 on success. + */ int dss_mainclk_state_enable(void) { int r; @@ -661,7 +672,7 @@ int dss_mainclk_state_enable(void) return -EINVAL; } else { r = dss_mainclk_enable(); - if (!r) + if (r >= 0) restore_all_ctx(); return 0; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 3469e38d4fb0..a9f61bd038ec 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -134,6 +134,13 @@ void dss_restore_context(void) #undef SR #undef RR +/* + * OMAP4 does not allow aggressive DSS clock cutting, so we must keep the + * clocks enabled during display use. These next two methods on OMAP4 + * increment and decrement the global mainclk counter. The needed opt + * clocks are enabled once during bootup and then handled by the pm + * framework. + */ bool dss_get_mainclk_state() { return dss.mainclk_state; @@ -141,20 +148,22 @@ bool dss_get_mainclk_state() int dss_mainclk_enable() { + int ret = 0; + if (!dss.mainclk_state) { - pm_runtime_get_sync(&dss.pdev->dev); - dss.mainclk_state = true; - return 0; + ret = pm_runtime_get_sync(&dss.pdev->dev); + if (ret >= 0) + dss.mainclk_state = true; } - return -EINVAL; + return ret; } void dss_mainclk_disable() { if (dss.mainclk_state) { - pm_runtime_put_sync(&dss.pdev->dev); dss.mainclk_state = false; + pm_runtime_put_sync(&dss.pdev->dev); } } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 6e51020b99f5..569d0b2012e3 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -226,7 +226,7 @@ struct bus_type *dss_get_bus(void); struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_sdi(void); struct regulator *dss_get_vdda_dac(void); -void dss_opt_clock_enable(void); +int dss_opt_clock_enable(void); void dss_opt_clock_disable(void); void save_all_ctx(void); void restore_all_ctx(void); @@ -462,7 +462,7 @@ int dispc_setup_plane(enum omap_plane plane, enum omap_dss_rotation_type rotation_type, u8 rotation, bool mirror, u8 global_alpha, enum omap_channel channel, - u32 puv_addr, u16 pic_width, u16 pic_height); + u32 puv_addr, u16 pic_height); bool dispc_go_busy(enum omap_channel channel); void dispc_go(enum omap_channel channel); diff --git a/drivers/video/omap2/dss/edid.c b/drivers/video/omap2/dss/edid.c index fbfbd415129e..68daf042054f 100644 --- a/drivers/video/omap2/dss/edid.c +++ b/drivers/video/omap2/dss/edid.c @@ -41,7 +41,7 @@ /*This is the structure which has all supported timing values that OMAP4 supports*/ -const struct omap_video_timings omap_hdmi_timings[31] = { +const struct omap_video_timings omap_hdmi_timings[32] = { {640, 480, 25200, 96, 16, 48, 2, 10, 33}, {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, @@ -60,7 +60,7 @@ const struct omap_video_timings omap_hdmi_timings[31] = { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, - {1280, 768, 71000, 128, 64, 192, 7 , 3, 20}, + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, @@ -73,7 +73,8 @@ const struct omap_video_timings omap_hdmi_timings[31] = { {1920, 1080, 148500, 44, 88, 80, 5, 4, 36}, {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, - {1680, 1050, 119000, 32, 48, 80, 6, 3, 21} } ; + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, + {1280, 800, 79500, 32, 48, 80, 6, 3, 14} } ; int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, struct omap_video_timings *timings) { @@ -137,7 +138,7 @@ int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd, struct omap_video_timing * support VESA timings? My monitor at home would pick 1920x1080 * otherwise, but that seems to not work well (monitor blanks out and * comes back, and picture doesn't fill full screen, but leaves a black * bar on left (native res is 2048x1152). However if I only consider * VESA timings, it picks 1680x1050 and the picture is stable and fills * whole screen.. */ - for (i = 14; i < 31; i++) { + for (i = 14; i < 32; i++) { const struct omap_video_timings *timings = &omap_hdmi_timings[i]; int hz, hscan, pixclock; diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index c1fa2d39d4c9..8106f1947fd2 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -113,8 +113,13 @@ enum hdmi_ioctl_cmds { #define HDMI_TXPHY_POWER_CTRL 0x8ul #define HDMI_TXPHY_PAD_CFG_CTRL 0xCul +struct hdmi_hvsync_pol { + int vsync_pol; + int hsync_pol; +}; + /*This is the structure which has all supported timing values that OMAP4 supports*/ -const struct omap_video_timings all_timings_direct[31] = { +const struct omap_video_timings all_timings_direct[32] = { {640, 480, 25200, 96, 16, 48, 2, 10, 33}, {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, @@ -133,7 +138,7 @@ const struct omap_video_timings all_timings_direct[31] = { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, - {1280, 768, 71000, 128, 64, 192, 7 , 3, 20}, + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, @@ -146,13 +151,25 @@ const struct omap_video_timings all_timings_direct[31] = { {1920, 1080, 148500, 44, 88, 80, 5, 4, 36}, {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, - {1680, 1050, 119000, 32, 48, 80, 6, 3, 21} }; + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, + {1280, 800, 79500, 32, 48, 80, 6, 3, 14} }; /*This is a static Mapping array which maps the timing values with corresponding CEA / VESA code*/ -int code_index[31] = {1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, +int code_index[32] = {1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, /* <--14 CEA 17--> vesa*/ 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, - 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39}; + 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B}; + +/*Static mapping of the Timing values with the corresponding Vsync and Hsync polarity*/ +const struct hdmi_hvsync_pol hvpol_mapping[32] = { + {0, 0}, {1, 1}, {1, 1}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {1, 1}, + {1, 1}, {1, 1}, {0, 0}, {0, 0}, + {1, 1}, {0, 0}, {0, 0}, {1, 1}, + {1, 1}, {1, 0}, {1, 0}, {1, 1}, + {1, 1}, {1, 1}, {0, 0}, {1, 0}, + {1, 0}, {1, 0}, {1, 1}, {1, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1} }; /*This is revere static mapping which maps the CEA / VESA code to the corresponding timing values*/ /* note: table is 10 entries per line to make it easier to find index.. */ @@ -166,7 +183,7 @@ int code_cea[39] = { int code_vesa[83] = { -1, -1, -1, -1, 14, -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, -1, 22, -1, -1, -1, - -1, -1, 28, 17, -1, -1, -1, -1, 18, -1, + -1, -1, 28, 17, -1, -1, -1, 31, 18, -1, -1, -1, 20, -1, -1, 21, -1, -1, -1, 19, -1, 29, 23, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, 25, -1, @@ -204,8 +221,12 @@ static void update_cfg (struct hdmi_config *cfg, struct omap_video_timings *timi cfg->vfp = timings->vfp; cfg->vsw = timings->vsw; cfg->pixel_clock = timings->pixel_clock; - cfg->v_pol = 1; // XXX get this from EDID - cfg->h_pol = 1; // XXX get this from EDID +} + +static void update_cfg_pol(struct hdmi_config *cfg, int code) +{ + cfg->v_pol = hvpol_mapping[code].vsync_pol; + cfg->h_pol = hvpol_mapping[code].hsync_pol; } static inline void hdmi_write_reg(u32 base, u16 idx, u32 val) @@ -812,6 +833,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) } update_cfg(&hdmi.cfg, p); + update_cfg_pol(&hdmi.cfg, code); code = get_timings_index(); dssdev->panel.timings = all_timings_direct[code]; @@ -1262,7 +1284,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) struct hdmi_cm cm = {-1}; DSSDBG("hdmi_get_code"); - for (i = 0; i < 31; i++) { + for (i = 0; i < 32; i++) { temp = all_timings_direct[i]; if ((temp.pixel_clock == timing->pixel_clock) && (temp.x_res == timing->x_res) && @@ -1560,19 +1582,7 @@ static int get_edid_timing_data(struct HDMI_EDID *edid) } -int nature_of_hdmi(void) +bool is_hdmi_interlaced(void) { - if ((hdmi.mode)) { - switch (hdmi.code) { - case 5: - case 6: - case 20: - case 21: - return INTERLACED; - default: - return PROGRESSIVE; - } - } - return PROGRESSIVE; + return hdmi.cfg.interlace; } - diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index c8a2f1ba7bad..2809dcd3c722 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -420,11 +420,7 @@ struct overlay_cache_data { bool manual_update; enum omap_overlay_zorder zorder; u32 p_uv_addr; /* relevent for NV12 format only */ - u16 pic_width; /* for ilace */ u16 pic_height; /* for ilace */ - u32 ibufpdev_offset; /* for ilace buffer & - progressive display device offset*/ - u16 ibufpdev_flag; /* for ilace buffer and progressive display device */ }; struct manager_cache_data { @@ -799,6 +795,9 @@ static int configure_overlay(enum omap_plane plane) } switch (c->color_mode) { + case OMAP_DSS_COLOR_NV12: + bpp = 8; + break; case OMAP_DSS_COLOR_RGB16: case OMAP_DSS_COLOR_ARGB16: case OMAP_DSS_COLOR_YUV2: @@ -864,28 +863,13 @@ static int configure_overlay(enum omap_plane plane) w -= 1; } } - if (cpu_is_omap44xx()){ - if ((paddr >= 0x60000000) && (paddr <= 0x7fffffff)) { - u16 height, pic_height; - s32 row_inc; - if (c->ilace == IBUF_PDEV) { - height = h/2; - pic_height = c->pic_height/2; - - calc_tiler_row_rotation(c->rotation, - w, height, c->color_mode, &row_inc, - &c->ibufpdev_offset, c->ilace, c->pic_width, - pic_height); - - c->ibufpdev_flag = 0; - } - } - } + r = dispc_scaling_decision(w, h, outw, outh, plane, c->color_mode, c->channel, c->rotation, c->min_x_decim, c->max_x_decim, c->min_y_decim, c->max_y_decim, &x_decim, &y_decim, &three_tap); + r = r ? : dispc_setup_plane(plane, paddr, c->screen_width, @@ -900,7 +884,6 @@ static int configure_overlay(enum omap_plane plane) c->global_alpha, c->channel, c->p_uv_addr, - c->pic_width, c->pic_height); if (r) { @@ -1045,9 +1028,11 @@ static int configure_dispc(void) /* Do nothing as of now as we dont * support Manager yet with WB */ + /*WB GO bit has to be used only in case of + capture mode and not in memory mode*/ + dispc_go_wb(); break; } - dispc_go_wb(); wb->shadow_dirty = false; dispc_enable_plane(OMAP_DSS_WB, 1); } @@ -1298,8 +1283,8 @@ static void dss_apply_irq_handler(void *data, u32 mask) omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | - DISPC_IRQ_EVSYNC_EVEN | (cpu_is_omap44xx()) ? - DISPC_IRQ_VSYNC2 : 0); + DISPC_IRQ_EVSYNC_EVEN | ((cpu_is_omap44xx()) ? + DISPC_IRQ_VSYNC2 : 0)); dss_cache.irq_enabled = false; end: @@ -1371,7 +1356,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) oc->screen_width = ovl->info.screen_width; oc->width = ovl->info.width; oc->height = ovl->info.height; - oc->pic_width = ovl->info.pic_width; oc->pic_height = ovl->info.pic_height; oc->color_mode = ovl->info.color_mode; oc->rotation = ovl->info.rotation; @@ -1509,7 +1493,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN | - (cpu_is_omap44xx()) ? DISPC_IRQ_VSYNC2 : 0); + ((cpu_is_omap44xx()) ? DISPC_IRQ_VSYNC2 : 0)); dss_cache.irq_enabled = true; } configure_dispc(); @@ -1989,15 +1973,6 @@ int omap_dss_get_num_overlay_managers(void) return num_managers; } -u16 *get_offset_cnt(int id, u32 *offset) -{ - struct overlay_cache_data *oc; - oc = &dss_cache.overlay_cache[id]; - *offset = oc->ibufpdev_offset; - return &oc->ibufpdev_flag; - -} - EXPORT_SYMBOL(omap_dss_get_num_overlay_managers); struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 896319232e18..6b461e83b297 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -279,7 +279,6 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, return size; } - static ssize_t overlay_decim_show(u16 min, u16 max, char *buf) { return snprintf(buf, PAGE_SIZE, "%d..%d\n", min, max); @@ -303,13 +302,10 @@ static ssize_t overlay_decim_store(u16 *min, u16 *max, char *last; *min = *max = simple_strtoul(buf, &last, 10); - if (last < buf + size) { + if (last < buf + size && *last == '.') { /* check for .. separator */ - if (last + 2 >= buf + size || - last[0] != '.' || - last[1] != '.') { + if (last + 2 >= buf + size || last[1] != '.') return -EINVAL; - } *max = simple_strtoul(last + 2, &last, 10); @@ -604,6 +600,10 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, ovl->manager = mgr; + /* do not set channel out if DSS is off */ + if (!dss_get_mainclk_state()) + return 0; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); /* XXX: on manual update display, in auto update mode, a bug happens * here. When an overlay is first enabled on LCD, then it's disabled, @@ -814,7 +814,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) mgr = lcd2_mgr; } } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC - && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { + && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { if (!lcd_mgr->device || force) { if (lcd_mgr->device) lcd_mgr->unset_device(lcd_mgr); |