Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/ivtv/ivtvfb.c
17701 views
1
/*
2
On Screen Display cx23415 Framebuffer driver
3
4
This module presents the cx23415 OSD (onscreen display) framebuffer memory
5
as a standard Linux /dev/fb style framebuffer device. The framebuffer has
6
support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
7
mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
8
local alpha. The colorspace is selectable between rgb & yuv.
9
Depending on the TV standard configured in the ivtv module at load time,
10
the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
11
Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
12
or 59.94 (NTSC)
13
14
Copyright (c) 2003 Matt T. Yourst <[email protected]>
15
16
Derived from drivers/video/vesafb.c
17
Portions (c) 1998 Gerd Knorr <[email protected]>
18
19
2.6 kernel port:
20
Copyright (C) 2004 Matthias Badaire
21
22
Copyright (C) 2004 Chris Kennedy <[email protected]>
23
24
Copyright (C) 2006 Ian Armstrong <[email protected]>
25
26
This program is free software; you can redistribute it and/or modify
27
it under the terms of the GNU General Public License as published by
28
the Free Software Foundation; either version 2 of the License, or
29
(at your option) any later version.
30
31
This program is distributed in the hope that it will be useful,
32
but WITHOUT ANY WARRANTY; without even the implied warranty of
33
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
GNU General Public License for more details.
35
36
You should have received a copy of the GNU General Public License
37
along with this program; if not, write to the Free Software
38
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39
*/
40
41
#include <linux/module.h>
42
#include <linux/kernel.h>
43
#include <linux/fb.h>
44
#include <linux/ivtvfb.h>
45
#include <linux/slab.h>
46
47
#ifdef CONFIG_MTRR
48
#include <asm/mtrr.h>
49
#endif
50
51
#include "ivtv-driver.h"
52
#include "ivtv-cards.h"
53
#include "ivtv-i2c.h"
54
#include "ivtv-udma.h"
55
#include "ivtv-mailbox.h"
56
#include "ivtv-firmware.h"
57
58
/* card parameters */
59
static int ivtvfb_card_id = -1;
60
static int ivtvfb_debug = 0;
61
static int osd_laced;
62
static int osd_depth;
63
static int osd_upper;
64
static int osd_left;
65
static int osd_yres;
66
static int osd_xres;
67
68
module_param(ivtvfb_card_id, int, 0444);
69
module_param_named(debug,ivtvfb_debug, int, 0644);
70
module_param(osd_laced, bool, 0444);
71
module_param(osd_depth, int, 0444);
72
module_param(osd_upper, int, 0444);
73
module_param(osd_left, int, 0444);
74
module_param(osd_yres, int, 0444);
75
module_param(osd_xres, int, 0444);
76
77
MODULE_PARM_DESC(ivtvfb_card_id,
78
"Only use framebuffer of the specified ivtv card (0-31)\n"
79
"\t\t\tdefault -1: initialize all available framebuffers");
80
81
MODULE_PARM_DESC(debug,
82
"Debug level (bitmask). Default: errors only\n"
83
"\t\t\t(debug = 3 gives full debugging)");
84
85
/* Why upper, left, xres, yres, depth, laced ? To match terminology used
86
by fbset.
87
Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
88
89
MODULE_PARM_DESC(osd_laced,
90
"Interlaced mode\n"
91
"\t\t\t0=off\n"
92
"\t\t\t1=on\n"
93
"\t\t\tdefault off");
94
95
MODULE_PARM_DESC(osd_depth,
96
"Bits per pixel - 8, 16, 32\n"
97
"\t\t\tdefault 8");
98
99
MODULE_PARM_DESC(osd_upper,
100
"Vertical start position\n"
101
"\t\t\tdefault 0 (Centered)");
102
103
MODULE_PARM_DESC(osd_left,
104
"Horizontal start position\n"
105
"\t\t\tdefault 0 (Centered)");
106
107
MODULE_PARM_DESC(osd_yres,
108
"Display height\n"
109
"\t\t\tdefault 480 (PAL)\n"
110
"\t\t\t 400 (NTSC)");
111
112
MODULE_PARM_DESC(osd_xres,
113
"Display width\n"
114
"\t\t\tdefault 640");
115
116
MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
117
MODULE_LICENSE("GPL");
118
119
/* --------------------------------------------------------------------- */
120
121
#define IVTVFB_DBGFLG_WARN (1 << 0)
122
#define IVTVFB_DBGFLG_INFO (1 << 1)
123
124
#define IVTVFB_DEBUG(x, type, fmt, args...) \
125
do { \
126
if ((x) & ivtvfb_debug) \
127
printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
128
} while (0)
129
#define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
130
#define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
131
132
/* Standard kernel messages */
133
#define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->instance , ## args)
134
#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->instance , ## args)
135
#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
136
137
/* --------------------------------------------------------------------- */
138
139
#define IVTV_OSD_MAX_WIDTH 720
140
#define IVTV_OSD_MAX_HEIGHT 576
141
142
#define IVTV_OSD_BPP_8 0x00
143
#define IVTV_OSD_BPP_16_444 0x03
144
#define IVTV_OSD_BPP_16_555 0x02
145
#define IVTV_OSD_BPP_16_565 0x01
146
#define IVTV_OSD_BPP_32 0x04
147
148
struct osd_info {
149
/* Physical base address */
150
unsigned long video_pbase;
151
/* Relative base address (relative to start of decoder memory) */
152
u32 video_rbase;
153
/* Mapped base address */
154
volatile char __iomem *video_vbase;
155
/* Buffer size */
156
u32 video_buffer_size;
157
158
#ifdef CONFIG_MTRR
159
/* video_base rounded down as required by hardware MTRRs */
160
unsigned long fb_start_aligned_physaddr;
161
/* video_base rounded up as required by hardware MTRRs */
162
unsigned long fb_end_aligned_physaddr;
163
#endif
164
165
/* Store the buffer offset */
166
int set_osd_coords_x;
167
int set_osd_coords_y;
168
169
/* Current dimensions (NOT VISIBLE SIZE!) */
170
int display_width;
171
int display_height;
172
int display_byte_stride;
173
174
/* Current bits per pixel */
175
int bits_per_pixel;
176
int bytes_per_pixel;
177
178
/* Frame buffer stuff */
179
struct fb_info ivtvfb_info;
180
struct fb_var_screeninfo ivtvfb_defined;
181
struct fb_fix_screeninfo ivtvfb_fix;
182
183
/* Used for a warm start */
184
struct fb_var_screeninfo fbvar_cur;
185
int blank_cur;
186
u32 palette_cur[256];
187
u32 pan_cur;
188
};
189
190
struct ivtv_osd_coords {
191
unsigned long offset;
192
unsigned long max_offset;
193
int pixel_stride;
194
int lines;
195
int x;
196
int y;
197
};
198
199
/* --------------------------------------------------------------------- */
200
201
/* ivtv API calls for framebuffer related support */
202
203
static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
204
u32 *fblength)
205
{
206
u32 data[CX2341X_MBOX_MAX_DATA];
207
int rc;
208
209
ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
210
rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
211
*fbbase = data[0];
212
*fblength = data[1];
213
return rc;
214
}
215
216
static int ivtvfb_get_osd_coords(struct ivtv *itv,
217
struct ivtv_osd_coords *osd)
218
{
219
struct osd_info *oi = itv->osd_info;
220
u32 data[CX2341X_MBOX_MAX_DATA];
221
222
ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
223
224
osd->offset = data[0] - oi->video_rbase;
225
osd->max_offset = oi->display_width * oi->display_height * 4;
226
osd->pixel_stride = data[1];
227
osd->lines = data[2];
228
osd->x = data[3];
229
osd->y = data[4];
230
return 0;
231
}
232
233
static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
234
{
235
struct osd_info *oi = itv->osd_info;
236
237
oi->display_width = osd->pixel_stride;
238
oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
239
oi->set_osd_coords_x += osd->x;
240
oi->set_osd_coords_y = osd->y;
241
242
return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
243
osd->offset + oi->video_rbase,
244
osd->pixel_stride,
245
osd->lines, osd->x, osd->y);
246
}
247
248
static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
249
{
250
int osd_height_limit = itv->is_out_50hz ? 576 : 480;
251
252
/* Only fail if resolution too high, otherwise fudge the start coords. */
253
if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
254
return -EINVAL;
255
256
/* Ensure we don't exceed display limits */
257
if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
258
IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
259
ivtv_window->top, ivtv_window->height);
260
ivtv_window->top = osd_height_limit - ivtv_window->height;
261
}
262
263
if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
264
IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
265
ivtv_window->left, ivtv_window->width);
266
ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
267
}
268
269
/* Set the OSD origin */
270
write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
271
272
/* How much to display */
273
write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
274
275
/* Pass this info back the yuv handler */
276
itv->yuv_info.osd_vis_w = ivtv_window->width;
277
itv->yuv_info.osd_vis_h = ivtv_window->height;
278
itv->yuv_info.osd_x_offset = ivtv_window->left;
279
itv->yuv_info.osd_y_offset = ivtv_window->top;
280
281
return 0;
282
}
283
284
static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
285
unsigned long ivtv_dest_addr, void __user *userbuf,
286
int size_in_bytes)
287
{
288
DEFINE_WAIT(wait);
289
int got_sig = 0;
290
291
mutex_lock(&itv->udma.lock);
292
/* Map User DMA */
293
if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
294
mutex_unlock(&itv->udma.lock);
295
IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
296
"Error with get_user_pages: %d bytes, %d pages returned\n",
297
size_in_bytes, itv->udma.page_count);
298
299
/* get_user_pages must have failed completely */
300
return -EIO;
301
}
302
303
IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
304
size_in_bytes, itv->udma.page_count);
305
306
ivtv_udma_prepare(itv);
307
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
308
/* if no UDMA is pending and no UDMA is in progress, then the DMA
309
is finished */
310
while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
311
test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
312
/* don't interrupt if the DMA is in progress but break off
313
a still pending DMA. */
314
got_sig = signal_pending(current);
315
if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
316
break;
317
got_sig = 0;
318
schedule();
319
}
320
finish_wait(&itv->dma_waitq, &wait);
321
322
/* Unmap Last DMA Xfer */
323
ivtv_udma_unmap(itv);
324
mutex_unlock(&itv->udma.lock);
325
if (got_sig) {
326
IVTV_DEBUG_INFO("User stopped OSD\n");
327
return -EINTR;
328
}
329
330
return 0;
331
}
332
333
static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
334
unsigned long dest_offset, int count)
335
{
336
DEFINE_WAIT(wait);
337
struct osd_info *oi = itv->osd_info;
338
339
/* Nothing to do */
340
if (count == 0) {
341
IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
342
return -EINVAL;
343
}
344
345
/* Check Total FB Size */
346
if ((dest_offset + count) > oi->video_buffer_size) {
347
IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
348
dest_offset + count, oi->video_buffer_size);
349
return -E2BIG;
350
}
351
352
/* Not fatal, but will have undesirable results */
353
if ((unsigned long)source & 3)
354
IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
355
(unsigned long)source);
356
357
if (dest_offset & 3)
358
IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
359
360
if (count & 3)
361
IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
362
363
/* Check Source */
364
if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
365
IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
366
(unsigned long)source);
367
368
IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
369
dest_offset, (unsigned long)source,
370
count);
371
return -EINVAL;
372
}
373
374
/* OSD Address to send DMA to */
375
dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
376
377
/* Fill Buffers */
378
return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
379
}
380
381
static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
382
size_t count, loff_t *ppos)
383
{
384
unsigned long p = *ppos;
385
void *dst;
386
int err = 0;
387
int dma_err;
388
unsigned long total_size;
389
struct ivtv *itv = (struct ivtv *) info->par;
390
unsigned long dma_offset =
391
IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
392
unsigned long dma_size;
393
u16 lead = 0, tail = 0;
394
395
if (info->state != FBINFO_STATE_RUNNING)
396
return -EPERM;
397
398
total_size = info->screen_size;
399
400
if (total_size == 0)
401
total_size = info->fix.smem_len;
402
403
if (p > total_size)
404
return -EFBIG;
405
406
if (count > total_size) {
407
err = -EFBIG;
408
count = total_size;
409
}
410
411
if (count + p > total_size) {
412
if (!err)
413
err = -ENOSPC;
414
count = total_size - p;
415
}
416
417
dst = (void __force *) (info->screen_base + p);
418
419
if (info->fbops->fb_sync)
420
info->fbops->fb_sync(info);
421
422
/* If transfer size > threshold and both src/dst
423
addresses are aligned, use DMA */
424
if (count >= 4096 &&
425
((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
426
/* Odd address = can't DMA. Align */
427
if ((unsigned long)dst & 3) {
428
lead = 4 - ((unsigned long)dst & 3);
429
if (copy_from_user(dst, buf, lead))
430
return -EFAULT;
431
buf += lead;
432
dst += lead;
433
}
434
/* DMA resolution is 32 bits */
435
if ((count - lead) & 3)
436
tail = (count - lead) & 3;
437
/* DMA the data */
438
dma_size = count - lead - tail;
439
dma_err = ivtvfb_prep_dec_dma_to_device(itv,
440
p + lead + dma_offset, (void __user *)buf, dma_size);
441
if (dma_err)
442
return dma_err;
443
dst += dma_size;
444
buf += dma_size;
445
/* Copy any leftover data */
446
if (tail && copy_from_user(dst, buf, tail))
447
return -EFAULT;
448
} else if (copy_from_user(dst, buf, count)) {
449
return -EFAULT;
450
}
451
452
if (!err)
453
*ppos += count;
454
455
return (err) ? err : count;
456
}
457
458
static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
459
{
460
DEFINE_WAIT(wait);
461
struct ivtv *itv = (struct ivtv *)info->par;
462
int rc = 0;
463
464
switch (cmd) {
465
case FBIOGET_VBLANK: {
466
struct fb_vblank vblank;
467
u32 trace;
468
469
memset(&vblank, 0, sizeof(struct fb_vblank));
470
471
vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
472
FB_VBLANK_HAVE_VSYNC;
473
trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
474
if (itv->is_out_50hz && trace > 312)
475
trace -= 312;
476
else if (itv->is_out_60hz && trace > 262)
477
trace -= 262;
478
if (trace == 1)
479
vblank.flags |= FB_VBLANK_VSYNCING;
480
vblank.count = itv->last_vsync_field;
481
vblank.vcount = trace;
482
vblank.hcount = 0;
483
if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
484
return -EFAULT;
485
return 0;
486
}
487
488
case FBIO_WAITFORVSYNC:
489
prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
490
if (!schedule_timeout(msecs_to_jiffies(50)))
491
rc = -ETIMEDOUT;
492
finish_wait(&itv->vsync_waitq, &wait);
493
return rc;
494
495
case IVTVFB_IOC_DMA_FRAME: {
496
struct ivtvfb_dma_frame args;
497
498
IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
499
if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
500
return -EFAULT;
501
502
return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
503
}
504
505
default:
506
IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
507
return -EINVAL;
508
}
509
return 0;
510
}
511
512
/* Framebuffer device handling */
513
514
static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
515
{
516
struct osd_info *oi = itv->osd_info;
517
struct ivtv_osd_coords ivtv_osd;
518
struct v4l2_rect ivtv_window;
519
int osd_mode = -1;
520
521
IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
522
523
/* Select color space */
524
if (var->nonstd) /* YUV */
525
write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
526
else /* RGB */
527
write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
528
529
/* Set the color mode */
530
switch (var->bits_per_pixel) {
531
case 8:
532
osd_mode = IVTV_OSD_BPP_8;
533
break;
534
case 32:
535
osd_mode = IVTV_OSD_BPP_32;
536
break;
537
case 16:
538
switch (var->green.length) {
539
case 4:
540
osd_mode = IVTV_OSD_BPP_16_444;
541
break;
542
case 5:
543
osd_mode = IVTV_OSD_BPP_16_555;
544
break;
545
case 6:
546
osd_mode = IVTV_OSD_BPP_16_565;
547
break;
548
default:
549
IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
550
}
551
break;
552
default:
553
IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
554
}
555
556
/* Set video mode. Although rare, the display can become scrambled even
557
if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
558
if (osd_mode != -1) {
559
ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
560
ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
561
}
562
563
oi->bits_per_pixel = var->bits_per_pixel;
564
oi->bytes_per_pixel = var->bits_per_pixel / 8;
565
566
/* Set the flicker filter */
567
switch (var->vmode & FB_VMODE_MASK) {
568
case FB_VMODE_NONINTERLACED: /* Filter on */
569
ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
570
break;
571
case FB_VMODE_INTERLACED: /* Filter off */
572
ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
573
break;
574
default:
575
IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
576
}
577
578
/* Read the current osd info */
579
ivtvfb_get_osd_coords(itv, &ivtv_osd);
580
581
/* Now set the OSD to the size we want */
582
ivtv_osd.pixel_stride = var->xres_virtual;
583
ivtv_osd.lines = var->yres_virtual;
584
ivtv_osd.x = 0;
585
ivtv_osd.y = 0;
586
ivtvfb_set_osd_coords(itv, &ivtv_osd);
587
588
/* Can't seem to find the right API combo for this.
589
Use another function which does what we need through direct register access. */
590
ivtv_window.width = var->xres;
591
ivtv_window.height = var->yres;
592
593
/* Minimum margin cannot be 0, as X won't allow such a mode */
594
if (!var->upper_margin)
595
var->upper_margin++;
596
if (!var->left_margin)
597
var->left_margin++;
598
ivtv_window.top = var->upper_margin - 1;
599
ivtv_window.left = var->left_margin - 1;
600
601
ivtvfb_set_display_window(itv, &ivtv_window);
602
603
/* Pass screen size back to yuv handler */
604
itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
605
itv->yuv_info.osd_full_h = ivtv_osd.lines;
606
607
/* Force update of yuv registers */
608
itv->yuv_info.yuv_forced_update = 1;
609
610
/* Keep a copy of these settings */
611
memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
612
613
IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
614
var->xres, var->yres,
615
var->xres_virtual, var->yres_virtual,
616
var->bits_per_pixel);
617
618
IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
619
var->left_margin, var->upper_margin);
620
621
IVTVFB_DEBUG_INFO("Display filter: %s\n",
622
(var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
623
IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
624
625
return 0;
626
}
627
628
static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
629
{
630
struct osd_info *oi = itv->osd_info;
631
632
IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
633
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
634
strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
635
fix->smem_start = oi->video_pbase;
636
fix->smem_len = oi->video_buffer_size;
637
fix->type = FB_TYPE_PACKED_PIXELS;
638
fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
639
fix->xpanstep = 1;
640
fix->ypanstep = 1;
641
fix->ywrapstep = 0;
642
fix->line_length = oi->display_byte_stride;
643
fix->accel = FB_ACCEL_NONE;
644
return 0;
645
}
646
647
/* Check the requested display mode, returning -EINVAL if we can't
648
handle it. */
649
650
static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
651
{
652
struct osd_info *oi = itv->osd_info;
653
int osd_height_limit;
654
u32 pixclock, hlimit, vlimit;
655
656
IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
657
658
/* Set base references for mode calcs. */
659
if (itv->is_out_50hz) {
660
pixclock = 84316;
661
hlimit = 776;
662
vlimit = 591;
663
osd_height_limit = 576;
664
}
665
else {
666
pixclock = 83926;
667
hlimit = 776;
668
vlimit = 495;
669
osd_height_limit = 480;
670
}
671
672
if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
673
var->transp.offset = 24;
674
var->transp.length = 8;
675
var->red.offset = 16;
676
var->red.length = 8;
677
var->green.offset = 8;
678
var->green.length = 8;
679
var->blue.offset = 0;
680
var->blue.length = 8;
681
}
682
else if (var->bits_per_pixel == 16) {
683
/* To find out the true mode, check green length */
684
switch (var->green.length) {
685
case 4:
686
var->red.offset = 8;
687
var->red.length = 4;
688
var->green.offset = 4;
689
var->green.length = 4;
690
var->blue.offset = 0;
691
var->blue.length = 4;
692
var->transp.offset = 12;
693
var->transp.length = 1;
694
break;
695
case 5:
696
var->red.offset = 10;
697
var->red.length = 5;
698
var->green.offset = 5;
699
var->green.length = 5;
700
var->blue.offset = 0;
701
var->blue.length = 5;
702
var->transp.offset = 15;
703
var->transp.length = 1;
704
break;
705
default:
706
var->red.offset = 11;
707
var->red.length = 5;
708
var->green.offset = 5;
709
var->green.length = 6;
710
var->blue.offset = 0;
711
var->blue.length = 5;
712
var->transp.offset = 0;
713
var->transp.length = 0;
714
break;
715
}
716
}
717
else {
718
IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
719
return -EINVAL;
720
}
721
722
/* Check the resolution */
723
if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
724
IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
725
var->xres, var->yres);
726
return -EINVAL;
727
}
728
729
/* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
730
if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
731
var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
732
var->xres_virtual < var->xres ||
733
var->yres_virtual < var->yres) {
734
IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
735
var->xres_virtual, var->yres_virtual);
736
return -EINVAL;
737
}
738
739
/* Some extra checks if in 8 bit mode */
740
if (var->bits_per_pixel == 8) {
741
/* Width must be a multiple of 4 */
742
if (var->xres & 3) {
743
IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
744
return -EINVAL;
745
}
746
if (var->xres_virtual & 3) {
747
IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
748
return -EINVAL;
749
}
750
}
751
else if (var->bits_per_pixel == 16) {
752
/* Width must be a multiple of 2 */
753
if (var->xres & 1) {
754
IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
755
return -EINVAL;
756
}
757
if (var->xres_virtual & 1) {
758
IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
759
return -EINVAL;
760
}
761
}
762
763
/* Now check the offsets */
764
if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
765
IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
766
var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
767
return -EINVAL;
768
}
769
770
/* Check pixel format */
771
if (var->nonstd > 1) {
772
IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
773
return -EINVAL;
774
}
775
776
/* Check video mode */
777
if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
778
((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
779
IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
780
return -EINVAL;
781
}
782
783
/* Check the left & upper margins
784
If the margins are too large, just center the screen
785
(enforcing margins causes too many problems) */
786
787
if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
788
var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
789
790
if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
791
var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
792
var->yres) / 2);
793
794
/* Maintain overall 'size' for a constant refresh rate */
795
var->right_margin = hlimit - var->left_margin - var->xres;
796
var->lower_margin = vlimit - var->upper_margin - var->yres;
797
798
/* Fixed sync times */
799
var->hsync_len = 24;
800
var->vsync_len = 2;
801
802
/* Non-interlaced / interlaced mode is used to switch the OSD filter
803
on or off. Adjust the clock timings to maintain a constant
804
vertical refresh rate. */
805
if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
806
var->pixclock = pixclock / 2;
807
else
808
var->pixclock = pixclock;
809
810
itv->osd_rect.width = var->xres;
811
itv->osd_rect.height = var->yres;
812
813
IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
814
var->xres, var->yres,
815
var->xres_virtual, var->yres_virtual,
816
var->bits_per_pixel);
817
818
IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
819
var->left_margin, var->upper_margin);
820
821
IVTVFB_DEBUG_INFO("Display filter: %s\n",
822
(var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
823
IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
824
return 0;
825
}
826
827
static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
828
{
829
struct ivtv *itv = (struct ivtv *) info->par;
830
IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
831
return _ivtvfb_check_var(var, itv);
832
}
833
834
static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
835
{
836
u32 osd_pan_index;
837
struct ivtv *itv = (struct ivtv *) info->par;
838
839
if (var->yoffset + info->var.yres > info->var.yres_virtual ||
840
var->xoffset + info->var.xres > info->var.xres_virtual)
841
return -EINVAL;
842
843
osd_pan_index = var->yoffset * info->fix.line_length
844
+ var->xoffset * info->var.bits_per_pixel / 8;
845
write_reg(osd_pan_index, 0x02A0C);
846
847
/* Pass this info back the yuv handler */
848
itv->yuv_info.osd_x_pan = var->xoffset;
849
itv->yuv_info.osd_y_pan = var->yoffset;
850
/* Force update of yuv registers */
851
itv->yuv_info.yuv_forced_update = 1;
852
/* Remember this value */
853
itv->osd_info->pan_cur = osd_pan_index;
854
return 0;
855
}
856
857
static int ivtvfb_set_par(struct fb_info *info)
858
{
859
int rc = 0;
860
struct ivtv *itv = (struct ivtv *) info->par;
861
862
IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
863
864
rc = ivtvfb_set_var(itv, &info->var);
865
ivtvfb_pan_display(&info->var, info);
866
ivtvfb_get_fix(itv, &info->fix);
867
ivtv_firmware_check(itv, "ivtvfb_set_par");
868
return rc;
869
}
870
871
static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
872
unsigned blue, unsigned transp,
873
struct fb_info *info)
874
{
875
u32 color, *palette;
876
struct ivtv *itv = (struct ivtv *)info->par;
877
878
if (regno >= info->cmap.len)
879
return -EINVAL;
880
881
color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
882
if (info->var.bits_per_pixel <= 8) {
883
write_reg(regno, 0x02a30);
884
write_reg(color, 0x02a34);
885
itv->osd_info->palette_cur[regno] = color;
886
return 0;
887
}
888
if (regno >= 16)
889
return -EINVAL;
890
891
palette = info->pseudo_palette;
892
if (info->var.bits_per_pixel == 16) {
893
switch (info->var.green.length) {
894
case 4:
895
color = ((red & 0xf000) >> 4) |
896
((green & 0xf000) >> 8) |
897
((blue & 0xf000) >> 12);
898
break;
899
case 5:
900
color = ((red & 0xf800) >> 1) |
901
((green & 0xf800) >> 6) |
902
((blue & 0xf800) >> 11);
903
break;
904
case 6:
905
color = (red & 0xf800 ) |
906
((green & 0xfc00) >> 5) |
907
((blue & 0xf800) >> 11);
908
break;
909
}
910
}
911
palette[regno] = color;
912
return 0;
913
}
914
915
/* We don't really support blanking. All this does is enable or
916
disable the OSD. */
917
static int ivtvfb_blank(int blank_mode, struct fb_info *info)
918
{
919
struct ivtv *itv = (struct ivtv *)info->par;
920
921
IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
922
switch (blank_mode) {
923
case FB_BLANK_UNBLANK:
924
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
925
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
926
break;
927
case FB_BLANK_NORMAL:
928
case FB_BLANK_HSYNC_SUSPEND:
929
case FB_BLANK_VSYNC_SUSPEND:
930
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
931
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
932
break;
933
case FB_BLANK_POWERDOWN:
934
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
935
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
936
break;
937
}
938
itv->osd_info->blank_cur = blank_mode;
939
return 0;
940
}
941
942
static struct fb_ops ivtvfb_ops = {
943
.owner = THIS_MODULE,
944
.fb_write = ivtvfb_write,
945
.fb_check_var = ivtvfb_check_var,
946
.fb_set_par = ivtvfb_set_par,
947
.fb_setcolreg = ivtvfb_setcolreg,
948
.fb_fillrect = cfb_fillrect,
949
.fb_copyarea = cfb_copyarea,
950
.fb_imageblit = cfb_imageblit,
951
.fb_cursor = NULL,
952
.fb_ioctl = ivtvfb_ioctl,
953
.fb_pan_display = ivtvfb_pan_display,
954
.fb_blank = ivtvfb_blank,
955
};
956
957
/* Restore hardware after firmware restart */
958
static void ivtvfb_restore(struct ivtv *itv)
959
{
960
struct osd_info *oi = itv->osd_info;
961
int i;
962
963
ivtvfb_set_var(itv, &oi->fbvar_cur);
964
ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
965
for (i = 0; i < 256; i++) {
966
write_reg(i, 0x02a30);
967
write_reg(oi->palette_cur[i], 0x02a34);
968
}
969
write_reg(oi->pan_cur, 0x02a0c);
970
}
971
972
/* Initialization */
973
974
975
/* Setup our initial video mode */
976
static int ivtvfb_init_vidmode(struct ivtv *itv)
977
{
978
struct osd_info *oi = itv->osd_info;
979
struct v4l2_rect start_window;
980
int max_height;
981
982
/* Color mode */
983
984
if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
985
osd_depth = 8;
986
oi->bits_per_pixel = osd_depth;
987
oi->bytes_per_pixel = oi->bits_per_pixel / 8;
988
989
/* Horizontal size & position */
990
991
if (osd_xres > 720)
992
osd_xres = 720;
993
994
/* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
995
if (osd_depth == 8)
996
osd_xres &= ~3;
997
else if (osd_depth == 16)
998
osd_xres &= ~1;
999
1000
start_window.width = osd_xres ? osd_xres : 640;
1001
1002
/* Check horizontal start (osd_left). */
1003
if (osd_left && osd_left + start_window.width > 721) {
1004
IVTVFB_ERR("Invalid osd_left - assuming default\n");
1005
osd_left = 0;
1006
}
1007
1008
/* Hardware coords start at 0, user coords start at 1. */
1009
osd_left--;
1010
1011
start_window.left = osd_left >= 0 ?
1012
osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
1013
1014
oi->display_byte_stride =
1015
start_window.width * oi->bytes_per_pixel;
1016
1017
/* Vertical size & position */
1018
1019
max_height = itv->is_out_50hz ? 576 : 480;
1020
1021
if (osd_yres > max_height)
1022
osd_yres = max_height;
1023
1024
start_window.height = osd_yres ?
1025
osd_yres : itv->is_out_50hz ? 480 : 400;
1026
1027
/* Check vertical start (osd_upper). */
1028
if (osd_upper + start_window.height > max_height + 1) {
1029
IVTVFB_ERR("Invalid osd_upper - assuming default\n");
1030
osd_upper = 0;
1031
}
1032
1033
/* Hardware coords start at 0, user coords start at 1. */
1034
osd_upper--;
1035
1036
start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
1037
1038
oi->display_width = start_window.width;
1039
oi->display_height = start_window.height;
1040
1041
/* Generate a valid fb_var_screeninfo */
1042
1043
oi->ivtvfb_defined.xres = oi->display_width;
1044
oi->ivtvfb_defined.yres = oi->display_height;
1045
oi->ivtvfb_defined.xres_virtual = oi->display_width;
1046
oi->ivtvfb_defined.yres_virtual = oi->display_height;
1047
oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
1048
oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
1049
oi->ivtvfb_defined.left_margin = start_window.left + 1;
1050
oi->ivtvfb_defined.upper_margin = start_window.top + 1;
1051
oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
1052
oi->ivtvfb_defined.nonstd = 0;
1053
1054
/* We've filled in the most data, let the usual mode check
1055
routine fill in the rest. */
1056
_ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1057
1058
/* Generate valid fb_fix_screeninfo */
1059
1060
ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1061
1062
/* Generate valid fb_info */
1063
1064
oi->ivtvfb_info.node = -1;
1065
oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1066
oi->ivtvfb_info.fbops = &ivtvfb_ops;
1067
oi->ivtvfb_info.par = itv;
1068
oi->ivtvfb_info.var = oi->ivtvfb_defined;
1069
oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1070
oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1071
oi->ivtvfb_info.fbops = &ivtvfb_ops;
1072
1073
/* Supply some monitor specs. Bogus values will do for now */
1074
oi->ivtvfb_info.monspecs.hfmin = 8000;
1075
oi->ivtvfb_info.monspecs.hfmax = 70000;
1076
oi->ivtvfb_info.monspecs.vfmin = 10;
1077
oi->ivtvfb_info.monspecs.vfmax = 100;
1078
1079
/* Allocate color map */
1080
if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1081
IVTVFB_ERR("abort, unable to alloc cmap\n");
1082
return -ENOMEM;
1083
}
1084
1085
/* Allocate the pseudo palette */
1086
oi->ivtvfb_info.pseudo_palette =
1087
kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
1088
1089
if (!oi->ivtvfb_info.pseudo_palette) {
1090
IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
1091
return -ENOMEM;
1092
}
1093
1094
return 0;
1095
}
1096
1097
/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1098
1099
static int ivtvfb_init_io(struct ivtv *itv)
1100
{
1101
struct osd_info *oi = itv->osd_info;
1102
1103
mutex_lock(&itv->serialize_lock);
1104
if (ivtv_init_on_first_open(itv)) {
1105
mutex_unlock(&itv->serialize_lock);
1106
IVTVFB_ERR("Failed to initialize ivtv\n");
1107
return -ENXIO;
1108
}
1109
mutex_unlock(&itv->serialize_lock);
1110
1111
if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
1112
&oi->video_buffer_size) < 0) {
1113
IVTVFB_ERR("Firmware failed to respond\n");
1114
return -EIO;
1115
}
1116
1117
/* The osd buffer size depends on the number of video buffers allocated
1118
on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1119
size to prevent any overlap. */
1120
oi->video_buffer_size = 1704960;
1121
1122
oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1123
oi->video_vbase = itv->dec_mem + oi->video_rbase;
1124
1125
if (!oi->video_vbase) {
1126
IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1127
oi->video_buffer_size, oi->video_pbase);
1128
return -EIO;
1129
}
1130
1131
IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1132
oi->video_pbase, oi->video_vbase,
1133
oi->video_buffer_size / 1024);
1134
1135
#ifdef CONFIG_MTRR
1136
{
1137
/* Find the largest power of two that maps the whole buffer */
1138
int size_shift = 31;
1139
1140
while (!(oi->video_buffer_size & (1 << size_shift))) {
1141
size_shift--;
1142
}
1143
size_shift++;
1144
oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1145
oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1146
oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1147
oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1148
if (mtrr_add(oi->fb_start_aligned_physaddr,
1149
oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
1150
MTRR_TYPE_WRCOMB, 1) < 0) {
1151
IVTVFB_INFO("disabled mttr\n");
1152
oi->fb_start_aligned_physaddr = 0;
1153
oi->fb_end_aligned_physaddr = 0;
1154
}
1155
}
1156
#endif
1157
1158
/* Blank the entire osd. */
1159
memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1160
1161
return 0;
1162
}
1163
1164
/* Release any memory we've grabbed & remove mtrr entry */
1165
static void ivtvfb_release_buffers (struct ivtv *itv)
1166
{
1167
struct osd_info *oi = itv->osd_info;
1168
1169
/* Release cmap */
1170
if (oi->ivtvfb_info.cmap.len)
1171
fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1172
1173
/* Release pseudo palette */
1174
if (oi->ivtvfb_info.pseudo_palette)
1175
kfree(oi->ivtvfb_info.pseudo_palette);
1176
1177
#ifdef CONFIG_MTRR
1178
if (oi->fb_end_aligned_physaddr) {
1179
mtrr_del(-1, oi->fb_start_aligned_physaddr,
1180
oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1181
}
1182
#endif
1183
1184
kfree(oi);
1185
itv->osd_info = NULL;
1186
}
1187
1188
/* Initialize the specified card */
1189
1190
static int ivtvfb_init_card(struct ivtv *itv)
1191
{
1192
int rc;
1193
1194
if (itv->osd_info) {
1195
IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1196
return -EBUSY;
1197
}
1198
1199
itv->osd_info = kzalloc(sizeof(struct osd_info),
1200
GFP_ATOMIC|__GFP_NOWARN);
1201
if (itv->osd_info == NULL) {
1202
IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1203
return -ENOMEM;
1204
}
1205
1206
/* Find & setup the OSD buffer */
1207
rc = ivtvfb_init_io(itv);
1208
if (rc) {
1209
ivtvfb_release_buffers(itv);
1210
return rc;
1211
}
1212
1213
/* Set the startup video mode information */
1214
if ((rc = ivtvfb_init_vidmode(itv))) {
1215
ivtvfb_release_buffers(itv);
1216
return rc;
1217
}
1218
1219
/* Register the framebuffer */
1220
if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1221
ivtvfb_release_buffers(itv);
1222
return -EINVAL;
1223
}
1224
1225
itv->osd_video_pbase = itv->osd_info->video_pbase;
1226
1227
/* Set the card to the requested mode */
1228
ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1229
1230
/* Set color 0 to black */
1231
write_reg(0, 0x02a30);
1232
write_reg(0, 0x02a34);
1233
1234
/* Enable the osd */
1235
ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1236
1237
/* Enable restart */
1238
itv->ivtvfb_restore = ivtvfb_restore;
1239
1240
/* Allocate DMA */
1241
ivtv_udma_alloc(itv);
1242
return 0;
1243
1244
}
1245
1246
static int __init ivtvfb_callback_init(struct device *dev, void *p)
1247
{
1248
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1249
struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1250
1251
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1252
if (ivtvfb_init_card(itv) == 0) {
1253
IVTVFB_INFO("Framebuffer registered on %s\n",
1254
itv->v4l2_dev.name);
1255
(*(int *)p)++;
1256
}
1257
}
1258
return 0;
1259
}
1260
1261
static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1262
{
1263
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1264
struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1265
struct osd_info *oi = itv->osd_info;
1266
1267
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1268
if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1269
IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
1270
itv->instance);
1271
return 0;
1272
}
1273
IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1274
itv->ivtvfb_restore = NULL;
1275
ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1276
ivtvfb_release_buffers(itv);
1277
itv->osd_video_pbase = 0;
1278
}
1279
return 0;
1280
}
1281
1282
static int __init ivtvfb_init(void)
1283
{
1284
struct device_driver *drv;
1285
int registered = 0;
1286
int err;
1287
1288
if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1289
printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1290
IVTV_MAX_CARDS - 1);
1291
return -EINVAL;
1292
}
1293
1294
drv = driver_find("ivtv", &pci_bus_type);
1295
err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1296
put_driver(drv);
1297
if (!registered) {
1298
printk(KERN_ERR "ivtvfb: no cards found\n");
1299
return -ENODEV;
1300
}
1301
return 0;
1302
}
1303
1304
static void ivtvfb_cleanup(void)
1305
{
1306
struct device_driver *drv;
1307
int err;
1308
1309
printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n");
1310
1311
drv = driver_find("ivtv", &pci_bus_type);
1312
err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1313
put_driver(drv);
1314
}
1315
1316
module_init(ivtvfb_init);
1317
module_exit(ivtvfb_cleanup);
1318
1319