#endif
#include "ivtv-driver.h"
-#include "ivtv-queue.h"
#include "ivtv-udma.h"
-#include "ivtv-irq.h"
-#include "ivtv-fileops.h"
#include "ivtv-mailbox.h"
-#include "ivtv-cards.h"
#include <media/ivtv-fb.h>
/* card parameters */
#define IVTV_OSD_BPP_32 0x04
struct osd_info {
- /* Timing info for modes */
- u32 pixclock;
- u32 hlimit;
- u32 vlimit;
-
/* Physical base address */
unsigned long video_pbase;
/* Relative base address (relative to start of decoder memory) */
unsigned long fb_end_aligned_physaddr;
#endif
+ /* Current osd mode */
+ int osd_mode;
+
/* Store the buffer offset */
int set_osd_coords_x;
int set_osd_coords_y;
unsigned long dest_offset, int count)
{
DEFINE_WAIT(wait);
+ struct osd_info *oi = itv->osd_info;
/* Nothing to do */
if (count == 0) {
}
/* Check Total FB Size */
- if ((dest_offset + count) > itv->osd_info->video_buffer_size) {
+ if ((dest_offset + count) > oi->video_buffer_size) {
IVTV_FB_WARN("ivtv_fb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
- dest_offset + count, itv->osd_info->video_buffer_size);
+ dest_offset + count, oi->video_buffer_size);
return -E2BIG;
}
}
/* OSD Address to send DMA to */
- dest_offset += IVTV_DEC_MEM_START + itv->osd_info->video_rbase;
+ dest_offset += IVTV_DEC_MEM_START + oi->video_rbase;
/* Fill Buffers */
return ivtv_fb_prep_dec_dma_to_device(itv, dest_offset, source, count);
case FBIO_WAITFORVSYNC:
prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
- if (!schedule_timeout(HZ/20)) rc = -ETIMEDOUT;
+ if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
finish_wait(&itv->vsync_waitq, &wait);
return rc;
}
default:
- IVTV_FB_ERR("Unknown IOCTL %d\n", cmd);
+ IVTV_FB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
return -EINVAL;
}
return 0;
static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
{
+ struct osd_info *oi = itv->osd_info;
struct ivtv_osd_coords ivtv_osd;
struct v4l2_rect ivtv_window;
+ int osd_mode = -1;
IVTV_FB_DEBUG_INFO("ivtvfb_set_var\n");
else /* RGB */
write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
- /* Set the color mode
- Although rare, occasionally things go wrong. The extra mode
- change seems to help... */
-
+ /* Set the color mode */
switch (var->bits_per_pixel) {
case 8:
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, IVTV_OSD_BPP_8);
+ osd_mode = IVTV_OSD_BPP_8;
break;
case 32:
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, IVTV_OSD_BPP_32);
+ osd_mode = IVTV_OSD_BPP_32;
break;
case 16:
switch (var->green.length) {
case 4:
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, IVTV_OSD_BPP_16_444);
+ osd_mode = IVTV_OSD_BPP_16_444;
break;
case 5:
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, IVTV_OSD_BPP_16_555);
+ osd_mode = IVTV_OSD_BPP_16_555;
break;
case 6:
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
- ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, IVTV_OSD_BPP_16_565);
+ osd_mode = IVTV_OSD_BPP_16_565;
break;
default:
IVTV_FB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
IVTV_FB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
}
- itv->osd_info->bits_per_pixel = var->bits_per_pixel;
- itv->osd_info->bytes_per_pixel = var->bits_per_pixel / 8;
+ /* Change osd mode if needed.
+ Although rare, things can go wrong. The extra mode
+ change seems to help... */
+ if (osd_mode != -1 && osd_mode != oi->osd_mode) {
+ ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
+ ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
+ oi->osd_mode = osd_mode;
+ }
+
+ oi->bits_per_pixel = var->bits_per_pixel;
+ oi->bytes_per_pixel = var->bits_per_pixel / 8;
/* Set the flicker filter */
switch (var->vmode & FB_VMODE_MASK) {
static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
{
struct osd_info *oi = itv->osd_info;
- int osd_height_limit = itv->is_50hz ? 576 : 480;
+ int osd_height_limit;
+ u32 pixclock, hlimit, vlimit;
IVTV_FB_DEBUG_INFO("ivtvfb_check_var\n");
+ /* Set base references for mode calcs. */
+ if (itv->is_50hz) {
+ pixclock = 84316;
+ hlimit = 776;
+ vlimit = 591;
+ osd_height_limit = 576;
+ }
+ else {
+ pixclock = 83926;
+ hlimit = 776;
+ vlimit = 495;
+ osd_height_limit = 480;
+ }
+
/* Check the bits per pixel */
if (osd_compat) {
if (var->bits_per_pixel != 32) {
var->blue.length = 8;
}
else if (var->bits_per_pixel == 16) {
- var->transp.offset = 0;
- var->transp.length = 0;
-
/* To find out the true mode, check green length */
switch (var->green.length) {
case 4:
var->green.length = 4;
var->blue.offset = 0;
var->blue.length = 4;
+ var->transp.offset = 12;
+ var->transp.length = 1;
break;
case 5:
var->red.offset = 10;
var->green.length = 5;
var->blue.offset = 0;
var->blue.length = 5;
+ var->transp.offset = 15;
+ var->transp.length = 1;
break;
default:
var->red.offset = 11;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
break;
}
}
}
/* Maintain overall 'size' for a constant refresh rate */
- var->right_margin = oi->hlimit - var->left_margin - var->xres;
- var->lower_margin = oi->vlimit - var->upper_margin - var->yres;
+ var->right_margin = hlimit - var->left_margin - var->xres;
+ var->lower_margin = vlimit - var->upper_margin - var->yres;
/* Fixed sync times */
var->hsync_len = 24;
/* Non-interlaced / interlaced mode is used to switch the OSD filter
on or off. Adjust the clock timings to maintain a constant
vertical refresh rate. */
- var->pixclock = oi->pixclock;
if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
- var->pixclock /= 2;
+ var->pixclock = pixclock / 2;
+ else
+ var->pixclock = pixclock;
IVTV_FB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
var->xres, var->yres,
struct v4l2_rect start_window;
int max_height;
- /* Set base references for mode calcs. */
- if (itv->is_50hz) {
- oi->pixclock = 84316;
- oi->hlimit = 776;
- oi->vlimit = 591;
- }
- else {
- oi->pixclock = 83926;
- oi->hlimit = 776;
- oi->vlimit = 495;
- }
-
/* Color mode */
if (osd_compat) osd_depth = 32;
oi->bits_per_pixel = osd_depth;
oi->bytes_per_pixel = oi->bits_per_pixel / 8;
+ /* Invalidate current osd mode to force a mode switch later */
+ oi->osd_mode = -1;
+
/* Horizontal size & position */
if (osd_xres > 720) osd_xres = 720;
{
struct osd_info *oi = itv->osd_info;
+ if (ivtv_init_on_first_open(itv)) {
+ IVTV_FB_ERR("Failed to initialize ivtv\n");
+ return -ENXIO;
+ }
+
ivtv_fb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
/* The osd buffer size depends on the number of video buffers allocated