@@ -121,10 +121,12 @@ static void vpbe_isr_odd_field(struct vpbe_display *disp_obj,
static irqreturn_t venc_isr(int irq, void *arg)
{
struct vpbe_display *disp_dev = (struct vpbe_display *)arg;
+ struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
struct vpbe_layer *layer;
static unsigned last_event;
unsigned event = 0;
int fid;
+ int ret;
int i;
if ((NULL == arg) || (NULL == disp_dev->dev[0]))
@@ -195,6 +197,10 @@ static irqreturn_t venc_isr(int irq, void *arg)
vpbe_isr_odd_field(disp_dev, layer);
}
}
+ ret = v4l2_subdev_call(vpbe_dev->venc, core, ioctl, VENC_INTERRUPT,
+ &event);
+ if (ret < 0)
+ v4l2_err(&vpbe_dev->v4l2_dev, "Error in getting Field ID 0\n");
return IRQ_HANDLED;
}
@@ -175,6 +175,13 @@ static int _osd_dm6446_vid0_pingpong(struct osd_state *sd,
return 0;
}
+static int osd_get_field_inversion(struct osd_state *sd)
+{
+ struct osd_state *osd = sd;
+
+ return osd->field_inversion;
+}
+
static void _osd_set_field_inversion(struct osd_state *sd, int enable)
{
unsigned fsinv = 0;
@@ -185,6 +192,365 @@ static void _osd_set_field_inversion(struct osd_state *sd, int enable)
osd_modify(sd, OSD_MODE_FSINV, fsinv, OSD_MODE);
}
+static void osd_set_field_inversion(struct osd_state *sd, int enable)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->field_inversion = (enable != 0);
+ _osd_set_field_inversion(sd, enable);
+
+ osd->pingpong = _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
+ osd->win[WIN_VID0].fb_base_phys,
+ &osd->win[WIN_VID0].lconfig);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void osd_get_background(struct osd_state *sd, enum osd_clut *clut,
+ unsigned char *clut_index)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ *clut = osd->backg_clut;
+ *clut_index = osd->backg_clut_index;
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_set_background(struct osd_state *sd, enum osd_clut clut,
+ unsigned char clut_index)
+{
+ u32 mode = 0;
+
+ if (clut == RAM_CLUT)
+ mode |= OSD_MODE_BCLUT;
+ mode |= clut_index;
+ osd_modify(sd, OSD_MODE_BCLUT | OSD_MODE_CABG, mode, OSD_MODE);
+}
+
+static void osd_set_background(struct osd_state *sd, enum osd_clut clut,
+ unsigned char clut_index)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->backg_clut = clut;
+ osd->backg_clut_index = clut_index;
+ _osd_set_background(sd, clut, clut_index);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static int osd_get_interpolation_filter(struct osd_state *sd)
+{
+ struct osd_state *osd = sd;
+
+ return osd->interpolation_filter;
+}
+
+static void _osd_set_interpolation_filter(struct osd_state *sd, int filter)
+{
+ struct osd_state *osd = sd;
+
+ if (osd->vpbe_type == VPBE_VERSION_3 ||
+ osd->vpbe_type == VPBE_VERSION_2)
+ osd_clear(sd, OSD_EXTMODE_EXPMDSEL, OSD_EXTMODE);
+
+ osd_modify(sd, OSD_MODE_EF, filter ? OSD_MODE_EF : 0, OSD_MODE);
+}
+
+static void osd_set_interpolation_filter(struct osd_state *sd, int filter)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->interpolation_filter = (filter != 0);
+ _osd_set_interpolation_filter(sd, filter);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void osd_get_cursor_config(struct osd_state *sd,
+ struct osd_cursor_config *cursor)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ *cursor = osd->cursor.config;
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_set_cursor_config(struct osd_state *sd,
+ const struct osd_cursor_config *cursor)
+{
+ struct osd_state *osd = sd;
+ unsigned rectcur = 0;
+
+ osd_write(sd, cursor->xsize, OSD_CURXL);
+ osd_write(sd, cursor->xpos, OSD_CURXP);
+
+ if (cursor->interlaced) {
+ osd_write(sd, cursor->ypos >> 1, OSD_CURYP);
+ if (osd->vpbe_type == VPBE_VERSION_1)
+ /* Must add 1 to ysize due to device erratum. */
+ osd_write(sd, (cursor->ysize >> 1) + 1, OSD_CURYL);
+ else
+ osd_write(sd, cursor->ysize >> 1, OSD_CURYL);
+ } else {
+ osd_write(sd, cursor->ypos, OSD_CURYP);
+ if (osd->vpbe_type == VPBE_VERSION_1)
+ /* Must add 1 to ysize due to device erratum. */
+ osd_write(sd, cursor->ysize + 1, OSD_CURYL);
+ else
+ osd_write(sd, cursor->ysize, OSD_CURYL);
+ }
+
+ if (cursor->clut == RAM_CLUT)
+ rectcur |= OSD_RECTCUR_CLUTSR;
+
+ rectcur |= (cursor->clut_index << OSD_RECTCUR_RCAD_SHIFT);
+ rectcur |= (cursor->h_width << OSD_RECTCUR_RCHW_SHIFT);
+ rectcur |= (cursor->v_width << OSD_RECTCUR_RCVW_SHIFT);
+ osd_modify(sd, OSD_RECTCUR_RCAD | OSD_RECTCUR_CLUTSR |
+ OSD_RECTCUR_RCHW | OSD_RECTCUR_RCVW, rectcur, OSD_RECTCUR);
+}
+
+static void osd_set_cursor_config(struct osd_state *sd,
+ struct osd_cursor_config *cursor)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ cursor->xpos = min_t(unsigned, cursor->xpos, (unsigned)OSD_CURXP_RCSX);
+ cursor->ypos = min_t(unsigned, cursor->ypos, (unsigned)OSD_CURYP_RCSY);
+ cursor->xsize =
+ min_t(unsigned, cursor->xsize, (unsigned)OSD_CURXL_RCSW);
+ cursor->ysize =
+ min_t(unsigned, cursor->ysize, (unsigned)OSD_CURYL_RCSH);
+ cursor->interlaced = (cursor->interlaced != 0);
+ if (cursor->interlaced) {
+ cursor->ysize &= ~1;
+ cursor->ypos &= ~1;
+ }
+ cursor->h_width &= (OSD_RECTCUR_RCHW >> OSD_RECTCUR_RCHW_SHIFT);
+ cursor->v_width &= (OSD_RECTCUR_RCVW >> OSD_RECTCUR_RCVW_SHIFT);
+ cursor->clut = (cursor->clut == RAM_CLUT) ? RAM_CLUT : ROM_CLUT;
+
+ osd->cursor.config = *cursor;
+ _osd_set_cursor_config(sd, cursor);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static int osd_cursor_is_enabled(struct osd_state *sd)
+{
+ struct osd_state *osd = sd;
+
+ return osd->cursor.is_enabled;
+}
+
+static void _osd_cursor_disable(struct osd_state *sd)
+{
+ osd_clear(sd, OSD_RECTCUR_RCACT, OSD_RECTCUR);
+}
+
+static void osd_cursor_disable(struct osd_state *sd)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->cursor.is_enabled = 0;
+ _osd_cursor_disable(sd);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_cursor_enable(struct osd_state *sd)
+{
+ osd_set(sd, OSD_RECTCUR_RCACT, OSD_RECTCUR);
+}
+
+static void osd_cursor_enable(struct osd_state *sd)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->cursor.is_enabled = 1;
+ _osd_cursor_enable(sd);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void osd_get_vid_expansion(struct osd_state *sd,
+ enum osd_h_exp_ratio *h_exp,
+ enum osd_v_exp_ratio *v_exp)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ *h_exp = osd->vid_h_exp;
+ *v_exp = osd->vid_v_exp;
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_set_vid_expansion(struct osd_state *sd,
+ enum osd_h_exp_ratio h_exp,
+ enum osd_v_exp_ratio v_exp)
+{
+ struct osd_state *osd = sd;
+ u32 mode = 0;
+ u32 extmode = 0;
+
+ switch (h_exp) {
+ case H_EXP_OFF:
+ break;
+ case H_EXP_9_OVER_8:
+ mode |= OSD_MODE_VHRSZ;
+ break;
+ case H_EXP_3_OVER_2:
+ extmode |= OSD_EXTMODE_VIDHRSZ15;
+ break;
+ }
+
+ switch (v_exp) {
+ case V_EXP_OFF:
+ break;
+ case V_EXP_6_OVER_5:
+ mode |= OSD_MODE_VVRSZ;
+ break;
+ }
+
+ if (osd->vpbe_type == VPBE_VERSION_3 ||
+ osd->vpbe_type == VPBE_VERSION_2)
+ osd_modify(sd, OSD_EXTMODE_VIDHRSZ15, extmode, OSD_EXTMODE);
+
+ osd_modify(sd, OSD_MODE_VHRSZ | OSD_MODE_VVRSZ, mode, OSD_MODE);
+}
+
+static int osd_set_vid_expansion(struct osd_state *sd,
+ enum osd_h_exp_ratio h_exp,
+ enum osd_v_exp_ratio v_exp)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ if (h_exp == H_EXP_3_OVER_2 && (osd->vpbe_type == VPBE_VERSION_1))
+ return -EINVAL;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->vid_h_exp = h_exp;
+ osd->vid_v_exp = v_exp;
+ _osd_set_vid_expansion(sd, h_exp, v_exp);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+ return 0;
+}
+
+static void osd_get_osd_expansion(struct osd_state *sd,
+ enum osd_h_exp_ratio *h_exp,
+ enum osd_v_exp_ratio *v_exp)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ *h_exp = osd->osd_h_exp;
+ *v_exp = osd->osd_v_exp;
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_set_osd_expansion(struct osd_state *sd,
+ enum osd_h_exp_ratio h_exp,
+ enum osd_v_exp_ratio v_exp)
+{
+ struct osd_state *osd = sd;
+ u32 mode = 0;
+ u32 extmode = 0;
+
+ switch (h_exp) {
+ case H_EXP_OFF:
+ break;
+ case H_EXP_9_OVER_8:
+ mode |= OSD_MODE_OHRSZ;
+ break;
+ case H_EXP_3_OVER_2:
+ extmode |= OSD_EXTMODE_OSDHRSZ15;
+ break;
+ }
+
+ switch (v_exp) {
+ case V_EXP_OFF:
+ break;
+ case V_EXP_6_OVER_5:
+ mode |= OSD_MODE_OVRSZ;
+ break;
+ }
+
+ if (osd->vpbe_type == VPBE_VERSION_3 ||
+ osd->vpbe_type == VPBE_VERSION_2)
+ osd_modify(sd, OSD_EXTMODE_OSDHRSZ15, extmode, OSD_EXTMODE);
+
+ osd_modify(sd, OSD_MODE_OHRSZ | OSD_MODE_OVRSZ, mode, OSD_MODE);
+}
+
+static int osd_set_osd_expansion(struct osd_state *sd,
+ enum osd_h_exp_ratio h_exp,
+ enum osd_v_exp_ratio v_exp)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ if (h_exp == H_EXP_3_OVER_2 && (osd->vpbe_type == VPBE_VERSION_1))
+ return -EINVAL;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->osd_h_exp = h_exp;
+ osd->osd_v_exp = v_exp;
+ _osd_set_osd_expansion(sd, h_exp, v_exp);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+ return 0;
+}
+
+static void osd_get_blink_attribute(struct osd_state *sd, int *enable,
+ enum osd_blink_interval *blink)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ *enable = osd->is_blinking;
+ *blink = osd->blink;
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
static void _osd_set_blink_attribute(struct osd_state *sd, int enable,
enum osd_blink_interval blink)
{
@@ -199,6 +565,29 @@ static void _osd_set_blink_attribute(struct osd_state *sd, int enable,
OSD_OSDATRMD);
}
+static void osd_set_blink_attribute(struct osd_state *sd, int enable,
+ enum osd_blink_interval blink)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->is_blinking = (enable != 0);
+ osd->blink = blink;
+ if (osd->win[WIN_OSD1].lconfig.pixfmt == PIXFMT_OSD_ATTR)
+ _osd_set_blink_attribute(sd, enable, blink);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static enum osd_rom_clut osd_get_rom_clut(struct osd_state *sd)
+{
+ struct osd_state *osd = sd;
+
+ return osd->rom_clut;
+}
+
static void _osd_set_rom_clut(struct osd_state *sd,
enum osd_rom_clut rom_clut)
{
@@ -208,6 +597,150 @@ static void _osd_set_rom_clut(struct osd_state *sd,
osd_set(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
}
+static void osd_set_rom_clut(struct osd_state *sd,
+ enum osd_rom_clut rom_clut)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->rom_clut = rom_clut;
+ _osd_set_rom_clut(sd, rom_clut);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_set_clut_ycbcr(struct osd_state *sd,
+ unsigned char clut_index,
+ unsigned char y, unsigned char cb,
+ unsigned char cr)
+{
+ /* wait until any previous writes to the CLUT RAM have completed */
+ while (osd_read(sd, OSD_MISCCTL) & OSD_MISCCTL_CPBSY)
+ cpu_relax();
+
+ osd_write(sd, (y << OSD_CLUTRAMYCB_Y_SHIFT) | cb, OSD_CLUTRAMYCB);
+ osd_write(sd, (cr << OSD_CLUTRAMCR_CR_SHIFT) | clut_index,
+ OSD_CLUTRAMCR);
+}
+
+static void osd_set_clut_ycbcr(struct osd_state *sd,
+ unsigned char clut_index, unsigned char y,
+ unsigned char cb, unsigned char cr)
+{
+ struct osd_state *osd = sd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->clut_ram[clut_index][0] = y;
+ osd->clut_ram[clut_index][1] = cb;
+ osd->clut_ram[clut_index][2] = cr;
+ _osd_set_clut_ycbcr(sd, clut_index, y, cb, cr);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void _osd_rgb_to_ycbcr(const unsigned char rgb[3],
+ unsigned char ycbcr[3])
+{
+ int y, cb, cr;
+ int r = rgb[0];
+ int g = rgb[1];
+ int b = rgb[2];
+ /*
+ * This conversion matrix corresponds to the conversion matrix used
+ * by the OSD to convert RGB values to YCbCr values. All coefficients
+ * have been scaled by a factor of 2^22.
+ */
+ static const int rgb_to_ycbcr[3][3] = {
+ {1250330, 2453618, 490352},
+ {-726093, -1424868, 2150957},
+ {2099836, -1750086, -349759}
+ };
+
+ y = rgb_to_ycbcr[0][0] * r + rgb_to_ycbcr[0][1] * g +
+ rgb_to_ycbcr[0][2] * b;
+ cb = rgb_to_ycbcr[1][0] * r + rgb_to_ycbcr[1][1] * g +
+ rgb_to_ycbcr[1][2] * b;
+ cr = rgb_to_ycbcr[2][0] * r + rgb_to_ycbcr[2][1] * g +
+ rgb_to_ycbcr[2][2] * b;
+
+ /* round and scale */
+ y = ((y + (1 << 21)) >> 22);
+ cb = ((cb + (1 << 21)) >> 22) + 128;
+ cr = ((cr + (1 << 21)) >> 22) + 128;
+
+ /* clip */
+ y = (y < 0) ? 0 : y;
+ y = (y > 255) ? 255 : y;
+ cb = (cb < 0) ? 0 : cb;
+ cb = (cb > 255) ? 255 : cb;
+ cr = (cr < 0) ? 0 : cr;
+ cr = (cr > 255) ? 255 : cr;
+
+ ycbcr[0] = y;
+ ycbcr[1] = cb;
+ ycbcr[2] = cr;
+}
+
+static void osd_set_clut_rgb(struct osd_state *sd, unsigned char clut_index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ struct osd_state *osd = sd;
+ unsigned char rgb[3], ycbcr[3];
+ unsigned long flags;
+
+ rgb[0] = r;
+ rgb[1] = g;
+ rgb[2] = b;
+ _osd_rgb_to_ycbcr(rgb, ycbcr);
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osd->clut_ram[clut_index][0] = ycbcr[0];
+ osd->clut_ram[clut_index][1] = ycbcr[1];
+ osd->clut_ram[clut_index][2] = ycbcr[2];
+ _osd_set_clut_ycbcr(sd, clut_index, ycbcr[0], ycbcr[1], ycbcr[2]);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static unsigned char osd_get_palette_map(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ unsigned char pixel_value)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned char clut_index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ switch (win->lconfig.pixfmt) {
+ case PIXFMT_1BPP:
+ clut_index = osdwin_state->palette_map[pixel_value & 0x1];
+ break;
+ case PIXFMT_2BPP:
+ clut_index = osdwin_state->palette_map[pixel_value & 0x3];
+ break;
+ case PIXFMT_4BPP:
+ clut_index = osdwin_state->palette_map[pixel_value & 0xf];
+ break;
+ default:
+ clut_index = 0;
+ break;
+ }
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+
+ return clut_index;
+}
+
static void _osd_set_palette_map(struct osd_state *sd,
enum osd_win_layer osdwin,
unsigned char pixel_value,
@@ -257,14 +790,55 @@ static void _osd_set_palette_map(struct osd_state *sd,
osd_modify(sd, bmp_mask, clut_index << bmp_shift, bmp_offset);
}
+static void osd_set_palette_map(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ unsigned char pixel_value,
+ unsigned char clut_index)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ switch (win->lconfig.pixfmt) {
+ case PIXFMT_1BPP:
+ osdwin_state->palette_map[pixel_value & 0x1] = clut_index;
+ break;
+ case PIXFMT_2BPP:
+ osdwin_state->palette_map[pixel_value & 0x3] = clut_index;
+ break;
+ case PIXFMT_4BPP:
+ osdwin_state->palette_map[pixel_value & 0xf] = clut_index;
+ break;
+ default:
+ spin_unlock_irqrestore(&osd->lock, flags);
+ return;
+ }
+
+ _osd_set_palette_map(sd, osdwin, pixel_value, clut_index,
+ win->lconfig.pixfmt);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static int osd_get_rec601_attenuation(struct osd_state *sd,
+ enum osd_win_layer osdwin)
+{
+ struct osd_state *osd = sd;
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+
+ return osdwin_state->rec601_attenuation;
+}
+
static void _osd_set_rec601_attenuation(struct osd_state *sd,
enum osd_win_layer osdwin, int enable)
{
switch (osdwin) {
case OSDWIN_OSD0:
- osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
- enable ? OSD_OSDWIN0MD_ATN0E : 0,
- OSD_OSDWIN0MD);
if (sd->vpbe_type == VPBE_VERSION_1)
osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
enable ? OSD_OSDWIN0MD_ATN0E : 0,
@@ -276,9 +850,6 @@ static void _osd_set_rec601_attenuation(struct osd_state *sd,
OSD_EXTMODE);
break;
case OSDWIN_OSD1:
- osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
- enable ? OSD_OSDWIN1MD_ATN1E : 0,
- OSD_OSDWIN1MD);
if (sd->vpbe_type == VPBE_VERSION_1)
osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
enable ? OSD_OSDWIN1MD_ATN1E : 0,
@@ -292,6 +863,35 @@ static void _osd_set_rec601_attenuation(struct osd_state *sd,
}
}
+static void osd_set_rec601_attenuation(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ int enable)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osdwin_state->rec601_attenuation = (enable != 0);
+ if (win->lconfig.pixfmt != PIXFMT_OSD_ATTR)
+ _osd_set_rec601_attenuation(sd, osdwin, enable);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static enum osd_blending_factor
+osd_get_blending_factor(struct osd_state *sd, enum osd_win_layer osdwin)
+{
+ struct osd_state *osd = sd;
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+
+ return osdwin_state->blend;
+}
+
static void _osd_set_blending_factor(struct osd_state *sd,
enum osd_win_layer osdwin,
enum osd_blending_factor blend)
@@ -308,6 +908,25 @@ static void _osd_set_blending_factor(struct osd_state *sd,
}
}
+static void osd_set_blending_factor(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ enum osd_blending_factor blend)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osdwin_state->blend = blend;
+ if (win->lconfig.pixfmt != PIXFMT_OSD_ATTR)
+ _osd_set_blending_factor(sd, osdwin, blend);
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
static void _osd_enable_rgb888_pixblend(struct osd_state *sd,
enum osd_win_layer osdwin)
{
@@ -388,6 +1007,28 @@ static void _osd_enable_color_key(struct osd_state *sd,
}
}
+static void osd_enable_color_key(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ unsigned colorkey)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osdwin_state->colorkey_blending = 1;
+ osdwin_state->colorkey = colorkey;
+ if (win->lconfig.pixfmt != PIXFMT_OSD_ATTR)
+ _osd_enable_color_key(sd, osdwin, colorkey,
+ win->lconfig.pixfmt);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
static void _osd_disable_color_key(struct osd_state *sd,
enum osd_win_layer osdwin)
{
@@ -421,6 +1062,69 @@ static void _osd_set_osd_clut(struct osd_state *sd,
}
}
+static void osd_disable_color_key(struct osd_state *sd,
+ enum osd_win_layer osdwin)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osdwin_state->colorkey_blending = 0;
+ if (win->lconfig.pixfmt != PIXFMT_OSD_ATTR)
+ _osd_disable_color_key(sd, osdwin);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static void osd_set_osd_clut(struct osd_state *sd, enum osd_win_layer osdwin,
+ enum osd_clut clut)
+{
+ struct osd_state *osd = sd;
+ enum osd_layer layer =
+ (osdwin == OSDWIN_OSD0) ? WIN_OSD0 : WIN_OSD1;
+ struct osd_window_state *win = &osd->win[layer];
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ osdwin_state->clut = clut;
+ if (win->lconfig.pixfmt != PIXFMT_OSD_ATTR)
+ _osd_set_osd_clut(sd, osdwin, clut);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+static enum osd_clut osd_get_osd_clut(struct osd_state *sd,
+ enum osd_win_layer osdwin)
+{
+ struct osd_state *osd = sd;
+ struct osd_osdwin_state *osdwin_state = &osd->osdwin[osdwin];
+
+ return osdwin_state->clut;
+}
+
+static void osd_get_zoom(struct osd_state *sd, enum osd_layer layer,
+ enum osd_zoom_factor *h_zoom,
+ enum osd_zoom_factor *v_zoom)
+{
+ struct osd_state *osd = sd;
+ struct osd_window_state *win = &osd->win[layer];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ *h_zoom = win->h_zoom;
+ *v_zoom = win->v_zoom;
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
enum osd_zoom_factor h_zoom,
enum osd_zoom_factor v_zoom)
@@ -454,6 +1158,31 @@ static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
break;
}
}
+static void osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
+ enum osd_zoom_factor h_zoom,
+ enum osd_zoom_factor v_zoom)
+{
+ struct osd_state *osd = sd;
+ struct osd_window_state *win = &osd->win[layer];
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ win->h_zoom = h_zoom;
+ win->v_zoom = v_zoom;
+ _osd_set_zoom(sd, layer, h_zoom, v_zoom);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+}
+
+
+static int osd_layer_is_enabled(struct osd_state *sd, enum osd_layer layer)
+{
+ struct osd_state *osd = sd;
+ struct osd_window_state *win = &osd->win[layer];
+
+ return win->is_enabled;
+}
static void _osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
{
@@ -497,7 +1226,7 @@ static void osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
static void _osd_enable_attribute_mode(struct osd_state *sd)
{
/* enable attribute mode for OSD1 */
- osd_set(sd, OSD_OSDWIN1MD_OASW, OSD_OSDWIN1MD);
+ osd_set(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1, OSD_OSDWIN1MD);
}
static void _osd_enable_layer(struct osd_state *sd, enum osd_layer layer)
@@ -811,7 +1540,7 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
case PIXFMT_8BPP:
case PIXFMT_RGB565:
if (osd->vpbe_type == VPBE_VERSION_1)
- bad_config = !is_vid_win(layer);
+ bad_config = !is_osd_win(layer);
break;
case PIXFMT_YCBCRI:
case PIXFMT_YCRCBI:
@@ -910,6 +1639,22 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
return 0;
}
+static int osd_try_layer_config(struct osd_state *sd, enum osd_layer layer,
+ struct osd_layer_config *lconfig)
+{
+ struct osd_state *osd = sd;
+ int reject_config;
+ unsigned long flags;
+
+ spin_lock_irqsave(&osd->lock, flags);
+
+ reject_config = try_layer_config(sd, layer, lconfig);
+
+ spin_unlock_irqrestore(&osd->lock, flags);
+
+ return reject_config;
+}
+
static void _osd_disable_vid_rgb888(struct osd_state *sd)
{
/*
@@ -1530,16 +2275,51 @@ static int osd_initialize(struct osd_state *osd)
}
static const struct vpbe_osd_ops osd_ops = {
+ .set_clut_ycbcr = osd_set_clut_ycbcr,
+ .set_clut_rgb = osd_set_clut_rgb,
+ .set_osd_clut = osd_set_osd_clut,
+ .get_osd_clut = osd_get_osd_clut,
+ .enable_color_key = osd_enable_color_key,
+ .disable_color_key = osd_disable_color_key,
+ .set_blending_factor = osd_set_blending_factor,
+ .get_blending_factor = osd_get_blending_factor,
+ .set_rec601_attenuation = osd_set_rec601_attenuation,
+ .get_rec601_attenuation = osd_get_rec601_attenuation,
+ .set_palette_map = osd_set_palette_map,
+ .get_palette_map = osd_get_palette_map,
+ .set_blink_attribute = osd_set_blink_attribute,
+ .get_blink_attribute = osd_get_blink_attribute,
+ .cursor_enable = osd_cursor_enable,
+ .cursor_disable = osd_cursor_disable,
+ .cursor_is_enabled = osd_cursor_is_enabled,
+ .set_cursor_config = osd_set_cursor_config,
+ .get_cursor_config = osd_get_cursor_config,
+ .set_field_inversion = osd_set_field_inversion,
+ .get_field_inversion = osd_get_field_inversion,
.initialize = osd_initialize,
.request_layer = osd_request_layer,
.release_layer = osd_release_layer,
.enable_layer = osd_enable_layer,
.disable_layer = osd_disable_layer,
+ .layer_is_enabled = osd_layer_is_enabled,
.set_layer_config = osd_set_layer_config,
+ .try_layer_config = osd_try_layer_config,
.get_layer_config = osd_get_layer_config,
.start_layer = osd_start_layer,
.set_left_margin = osd_set_left_margin,
.set_top_margin = osd_set_top_margin,
+ .set_interpolation_filter = osd_set_interpolation_filter,
+ .get_interpolation_filter = osd_get_interpolation_filter,
+ .set_osd_expansion = osd_set_osd_expansion,
+ .get_osd_expansion = osd_get_osd_expansion,
+ .set_vid_expansion = osd_set_vid_expansion,
+ .get_vid_expansion = osd_get_vid_expansion,
+ .set_zoom = osd_set_zoom,
+ .get_zoom = osd_get_zoom,
+ .set_background = osd_set_background,
+ .get_background = osd_get_background,
+ .set_rom_clut = osd_set_rom_clut,
+ .get_rom_clut = osd_get_rom_clut,
};
static int osd_probe(struct platform_device *pdev)
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <linux/slab.h>
+#include <linux/v4l2-dv-timings.h>
#include <mach/hardware.h>
#include <mach/mux.h>
@@ -31,6 +32,7 @@
#include <linux/io.h>
+#include <media/v4l2-mediabus.h>
#include <media/davinci/vpbe_types.h>
#include <media/davinci/vpbe_venc.h>
#include <media/davinci/vpss.h>
@@ -66,6 +68,7 @@ struct venc_state {
struct v4l2_subdev sd;
struct venc_callback *callback;
struct venc_platform_data *pdata;
+ enum v4l2_mbus_pixelcode if_params;
struct device *pdev;
u32 output;
v4l2_std_id std;
@@ -539,6 +542,10 @@ static long venc_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg)
{
+ struct venc_callback *next, *prev, *callback;
+ struct venc_state *venc = to_state(sd);
+ unsigned long flags;
+ unsigned event = 0;
u32 val;
switch (cmd) {
@@ -547,6 +554,42 @@ static long venc_ioctl(struct v4l2_subdev *sd,
*((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
VENC_VSTAT_FIDST);
break;
+ case VENC_REG_CALLBACK:
+ spin_lock_irqsave(&venc->lock, flags);
+ callback = (struct venc_callback *)arg;
+ next = venc->callback;
+ venc->callback = callback;
+ callback->next = next;
+ spin_unlock_irqrestore(&venc->lock, flags);
+ break;
+ case VENC_UNREG_CALLBACK:
+ spin_lock_irqsave(&venc->lock, flags);
+ callback = (struct venc_callback *)arg;
+ prev = venc->callback;
+ if (!prev)
+ return -EINVAL;
+
+ if (prev == callback) {
+ venc->callback = callback->next;
+ } else {
+ while (prev->next && (prev->next != callback))
+ prev = prev->next;
+ if (!prev->next)
+ return -EINVAL;
+ else
+ prev->next = callback->next;
+ }
+ spin_unlock_irqrestore(&venc->lock, flags);
+ break;
+ case VENC_INTERRUPT:
+ callback = venc->callback;
+ event = *((unsigned *)arg);
+ while (callback) {
+ if (callback->mask & event)
+ callback->handler(event, callback->arg);
+ callback = callback->next;
+ }
+ break;
default:
v4l2_err(sd, "Wrong IOCTL cmd\n");
break;
@@ -327,14 +327,59 @@ struct osd_cursor_state {
struct osd_state;
struct vpbe_osd_ops {
+ void (*set_clut_ycbcr)(struct osd_state *sd,
+ unsigned char clut_index, unsigned char y,
+ unsigned char cb, unsigned char cr);
+ void (*set_clut_rgb)(struct osd_state *sd, unsigned char clut_index,
+ unsigned char r, unsigned char g,
+ unsigned char b);
+ void (*set_osd_clut)(struct osd_state *sd, enum osd_win_layer osdwin,
+ enum osd_clut clut);
+ enum osd_clut (*get_osd_clut)(struct osd_state *sd,
+ enum osd_win_layer osdwin);
+ void (*enable_color_key)(struct osd_state *sd,
+ enum osd_win_layer osdwin, unsigned colorkey);
+ void (*disable_color_key)(struct osd_state *sd,
+ enum osd_win_layer osdwin);
+ void (*set_blending_factor)(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ enum osd_blending_factor blend);
+ enum osd_blending_factor (*get_blending_factor)(struct osd_state *sd,
+ enum osd_win_layer osdwin);
+ void (*set_rec601_attenuation)(struct osd_state *sd,
+ enum osd_win_layer osdwin, int enable);
+ int (*get_rec601_attenuation)(struct osd_state *sd,
+ enum osd_win_layer osdwin);
+ void (*set_palette_map)(struct osd_state *sd,
+ enum osd_win_layer osdwin,
+ unsigned char pixel_value,
+ unsigned char clut_index);
+ unsigned char (*get_palette_map)(struct osd_state *sd,
+ enum osd_win_layer osdwin, unsigned char pixel_value);
+ void (*set_blink_attribute)(struct osd_state *sd, int enable,
+ enum osd_blink_interval blink);
+ void (*get_blink_attribute)(struct osd_state *sd, int *enable,
+ enum osd_blink_interval *blink);
+ void (*cursor_enable)(struct osd_state *sd);
+ void (*cursor_disable)(struct osd_state *sd);
+ int (*cursor_is_enabled)(struct osd_state *sd);
+ void (*set_cursor_config)(struct osd_state *sd,
+ struct osd_cursor_config *cursor);
+ void (*get_cursor_config)(struct osd_state *sd,
+ struct osd_cursor_config *cursor);
+ void (*set_field_inversion)(struct osd_state *sd, int enable);
+ int (*get_field_inversion)(struct osd_state *sd);
int (*initialize)(struct osd_state *sd);
int (*request_layer)(struct osd_state *sd, enum osd_layer layer);
void (*release_layer)(struct osd_state *sd, enum osd_layer layer);
int (*enable_layer)(struct osd_state *sd, enum osd_layer layer,
int otherwin);
void (*disable_layer)(struct osd_state *sd, enum osd_layer layer);
+ int (*layer_is_enabled)(struct osd_state *sd, enum osd_layer layer);
int (*set_layer_config)(struct osd_state *sd, enum osd_layer layer,
struct osd_layer_config *lconfig);
+ int (*try_layer_config)(struct osd_state *sd, enum osd_layer layer,
+ struct osd_layer_config *lconfig);
void (*get_layer_config)(struct osd_state *sd, enum osd_layer layer,
struct osd_layer_config *lconfig);
void (*start_layer)(struct osd_state *sd, enum osd_layer layer,
@@ -343,6 +388,13 @@ struct vpbe_osd_ops {
void (*set_left_margin)(struct osd_state *sd, u32 val);
void (*set_top_margin)(struct osd_state *sd, u32 val);
void (*set_interpolation_filter)(struct osd_state *sd, int filter);
+ int (*get_interpolation_filter)(struct osd_state *sd);
+ int (*set_osd_expansion)(struct osd_state *sd,
+ enum osd_h_exp_ratio h_exp,
+ enum osd_v_exp_ratio v_exp);
+ void (*get_osd_expansion)(struct osd_state *sd,
+ enum osd_h_exp_ratio *h_exp,
+ enum osd_v_exp_ratio *v_exp);
int (*set_vid_expansion)(struct osd_state *sd,
enum osd_h_exp_ratio h_exp,
enum osd_v_exp_ratio v_exp);
@@ -352,6 +404,16 @@ struct vpbe_osd_ops {
void (*set_zoom)(struct osd_state *sd, enum osd_layer layer,
enum osd_zoom_factor h_zoom,
enum osd_zoom_factor v_zoom);
+ void (*get_zoom)(struct osd_state *sd, enum osd_layer layer,
+ enum osd_zoom_factor *h_zoom,
+ enum osd_zoom_factor *v_zoom);
+ void (*set_background)(struct osd_state *sd, enum osd_clut clut,
+ unsigned char clut_index);
+ void (*get_background)(struct osd_state *sd, enum osd_clut *clut,
+ unsigned char *clut_index);
+ void (*set_rom_clut)(struct osd_state *sd,
+ enum osd_rom_clut rom_clut);
+ enum osd_rom_clut (*get_rom_clut)(struct osd_state *sd);
};
struct osd_state {
@@ -29,6 +29,24 @@
#define VENC_FIRST_FIELD BIT(1)
#define VENC_SECOND_FIELD BIT(2)
+/**
+ * struct venc_callback
+ * @next: used internally by the venc driver to maintain a linked list of
+ * callbacks
+ * @mask: a bitmask specifying the venc event(s) for which the
+ * callback will be invoked
+ * @handler: the callback routine
+ * @arg: a null pointer that is passed as the second argument to the callback
+ * routine
+ */
+struct venc_callback {
+ struct venc_callback *next;
+ char *owner;
+ unsigned mask;
+ void (*handler) (unsigned event, void *arg);
+ void *arg;
+};
+
struct venc_platform_data {
int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
int field);
@@ -42,6 +60,9 @@ struct venc_platform_data {
enum venc_ioctls {
VENC_GET_FLD = 1,
+ VENC_REG_CALLBACK,
+ VENC_UNREG_CALLBACK,
+ VENC_INTERRUPT,
};
/* exported functions */