1 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3 #include <linux/kernel.h>
4 #include <linux/export.h>
10 *clip_format &= 0x0000ffff;
12 *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
18 *hps_ctrl |= (source << 30) | (sync << 28);
21 static void calculate_hxo_and_hyo(
struct saa7146_vv *vv,
u32* hps_h_scale,
u32* hps_ctrl)
28 *hps_h_scale &= ~(
MASK_B0 | 0xf00);
29 *hps_h_scale |= (hxo << 0);
32 *hps_ctrl |= (hyo << 12);
46 } hps_h_coeff_tab [] = {
47 {0x00, 2}, {0x02, 4}, {0x00, 4}, {0x06, 8}, {0x02, 8},
48 {0x08, 8}, {0x00, 8}, {0x1E, 16}, {0x0E, 8}, {0x26, 8},
49 {0x06, 8}, {0x42, 8}, {0x02, 8}, {0x80, 8}, {0x00, 8},
50 {0xFE, 16}, {0xFE, 8}, {0x7E, 8}, {0x7E, 8}, {0x3E, 8},
51 {0x3E, 8}, {0x1E, 8}, {0x1E, 8}, {0x0E, 8}, {0x0E, 8},
52 {0x06, 8}, {0x06, 8}, {0x02, 8}, {0x02, 8}, {0x00, 8},
53 {0x00, 8}, {0xFE, 16}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
54 {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
55 {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8},
56 {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0x7E, 8},
57 {0x7E, 8}, {0x3E, 8}, {0x3E, 8}, {0x1E, 8}, {0x1E, 8},
58 {0x0E, 8}, {0x0E, 8}, {0x06, 8}, {0x06, 8}, {0x02, 8},
59 {0x02, 8}, {0x00, 8}, {0x00, 8}, {0xFE, 16}
63 static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
66 static int calculate_h_scale_registers(
struct saa7146_dev *dev,
67 int in_x,
int out_x,
int flip_lr,
68 u32* hps_ctrl,
u32* hps_v_gain,
u32* hps_h_prescale,
u32* hps_h_scale)
71 u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
73 u32 xim = 0,
xp = 0, xsci =0;
78 u32 h_atten = 0,
i = 0;
101 if ( 0 != flip_lr ) {
106 while (in_x / xpsc >= 384 )
112 while ( in_x / xpsc >= 768 )
124 cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].
hps_coeff;
130 if ( (in_x == out_x) && ( 1 == xpsc ) )
133 xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc;
153 h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].
weight_sum;
155 for (
i = 0; h_attenuation[
i] != 0;
i++) {
156 if (h_attenuation[
i] >= h_atten)
168 else if ( xsci < 0x600)
170 else if ( xsci < 0x680)
172 else if ( xsci < 0x700)
179 *hps_v_gain |= (pfuv << 24);
181 *hps_h_scale &= ~(
MASK_W1 | 0xf000);
182 *hps_h_scale |= (xim << 31) | (
xp << 24) | (xsci << 12);
184 *hps_h_prescale |= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0);
192 } hps_v_coeff_tab [] = {
193 {0x0100, 2}, {0x0102, 4}, {0x0300, 4}, {0x0106, 8}, {0x0502, 8},
194 {0x0708, 8}, {0x0F00, 8}, {0x011E, 16}, {0x110E, 16}, {0x1926, 16},
195 {0x3906, 16}, {0x3D42, 16}, {0x7D02, 16}, {0x7F80, 16}, {0xFF00, 16},
196 {0x01FE, 32}, {0x01FE, 32}, {0x817E, 32}, {0x817E, 32}, {0xC13E, 32},
197 {0xC13E, 32}, {0xE11E, 32}, {0xE11E, 32}, {0xF10E, 32}, {0xF10E, 32},
198 {0xF906, 32}, {0xF906, 32}, {0xFD02, 32}, {0xFD02, 32}, {0xFF00, 32},
199 {0xFF00, 32}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
200 {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
201 {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64},
202 {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x817E, 64},
203 {0x817E, 64}, {0xC13E, 64}, {0xC13E, 64}, {0xE11E, 64}, {0xE11E, 64},
204 {0xF10E, 64}, {0xF10E, 64}, {0xF906, 64}, {0xF906, 64}, {0xFD02, 64},
205 {0xFD02, 64}, {0xFF00, 64}, {0xFF00, 64}, {0x01FE, 128}
209 static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
213 int in_y,
int out_y,
u32* hps_v_scale,
u32* hps_v_gain)
218 u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0;
220 u32 dcgy = 0, cya_cyb = 0;
223 u32 v_atten = 0,
i = 0;
226 if ( in_y < out_y ) {
235 if( 2*out_y >= in_y) {
241 if( 4*out_y >= in_y ) {
254 ysci = ((1024 * in_y) / (out_y + 1)) - 1024;
262 ypo = ype + (ysci / 64);
268 ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10;
271 ypo = ype = ((ysci + 15) / 16);
281 yacl = ( ysci / (1024 - ysci) );
285 cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].
hps_coeff;
288 v_atten = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].
weight_sum;
290 for (
i = 0; v_attenuation[
i] != 0;
i++) {
291 if (v_attenuation[
i] >= v_atten)
299 *hps_v_scale |= (yacm << 31) | (ysci << 21) | (yacl << 15) | (ypo << 8 ) | (ype << 1);
302 *hps_v_gain |= (dcgy << 16) | (cya_cyb << 0);
314 if( (0 > *count) || (
NULL == values) ) {
321 if( values[low] > values[
high] ) {
331 if( values[cur] != values[
next])
346 int width = vv->
ov.win.w.width;
348 int clipcount = vv->
ov.nclips;
355 int cnt_line = 0, cnt_pixel = 0;
357 int x[32],
y[32],
w[32],
h[32];
360 memset(&line_list[0], 0x00,
sizeof(
u32)*32);
361 memset(&pixel_list[0], 0x00,
sizeof(
u32)*32);
365 for(i = 0; i < clipcount; i++) {
366 int l = 0,
r = 0,
t = 0,
b = 0;
368 x[
i] = vv->
ov.clips[
i].c.left;
369 y[
i] = vv->
ov.clips[
i].c.top;
370 w[
i] = vv->
ov.clips[
i].c.width;
371 h[
i] = vv->
ov.clips[
i].c.height;
374 x[
i] += w[
i]; w[
i] = -w[
i];
377 y[
i] += h[
i]; h[
i] = -h[
i];
380 w[
i] += x[
i]; x[
i] = 0;
383 h[
i] += y[
i]; y[
i] = 0;
385 if( 0 != vv->
vflip ) {
386 y[
i] = height - y[
i] - h[
i];
395 pixel_list[ 2*
i ] =
min_t(
int, l, width);
396 pixel_list[(2*
i)+1] =
min_t(
int,
r, width);
398 line_list[ 2*
i ] =
min_t(
int,
t, height);
399 line_list[(2*
i)+1] =
min_t(
int,
b, height);
403 cnt_line = cnt_pixel = 2*clipcount;
404 sort_and_eliminate( &pixel_list[0], &cnt_pixel );
405 sort_and_eliminate( &line_list[0], &cnt_line );
408 numdwords =
max_t(
int, (cnt_line+1), (cnt_pixel+1))*2;
409 numdwords =
max_t(
int, 4, numdwords);
410 numdwords =
min_t(
int, 64, numdwords);
413 for(i = 0; i < cnt_pixel; i++) {
416 for(i = 0; i < cnt_line; i++) {
421 for(
j = 0;
j < clipcount;
j++) {
423 for(i = 0; i < cnt_pixel; i++) {
428 if( pixel_list[i] < (x[
j] + w[
j])) {
430 if ( pixel_list[i] >= x[j] ) {
435 for(i = 0; i < cnt_line; i++) {
440 if( line_list[i] < (y[j] + h[j]) ) {
442 if( line_list[i] >= y[j] ) {
450 *arbtr_ctrl &= 0xffff00ff;
451 *arbtr_ctrl |= 0x00001c00;
461 *clip_format &= 0xfffffff7;
463 *clip_format |= 0x00000008;
465 *clip_format |= 0x00000000;
470 static void saa7146_disable_clipping(
struct saa7146_dev *dev)
485 static void saa7146_set_clipping_rect(
struct saa7146_fh *fh)
495 if (vv->
ov.nclips == 0) {
496 saa7146_disable_clipping(dev);
503 calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
506 clip_format &= 0xffff0008;
526 static void saa7146_set_window(
struct saa7146_dev *dev,
int width,
int height,
enum v4l2_field field)
533 u32 hps_v_scale = 0, hps_v_gain = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0;
538 calculate_v_scale_registers(dev, field, vv->
standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
544 calculate_h_scale_registers(dev, vv->
standard->h_pixels, width, vv->
hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
547 calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
548 calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl);
567 int b_depth = vv->
ov_fmt->depth;
568 int b_bpl = vv->
ov_fb.fmt.bytesperline;
581 vdma1.
pitch = 2*b_bpl;
582 if ( 0 == vv->
vflip ) {
583 vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
584 vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
585 vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
588 vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
589 vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
590 vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
596 vdma1.base_odd = vdma1.prot_addr;
599 vdma1.base_odd = vdma1.prot_addr;
602 vdma1.base_odd = vdma1.base_even;
603 vdma1.base_even = vdma1.prot_addr;
607 if ( 0 != vv->
vflip ) {
611 vdma1.base_page = sfmt->
swap;
622 calculate_output_format_register(dev,palette,&clip_format);
639 hps_ctrl |= (source << 30) | (sync << 28);
655 saa7146_set_window(dev, vv->
ov.win.w.width, vv->
ov.win.w.height, vv->
ov.win.field);
656 saa7146_set_position(dev, vv->
ov.win.w.left, vv->
ov.win.w.top, vv->
ov.win.w.height, vv->
ov.win.field, vv->
ov_fmt->pixelformat);
657 saa7146_set_output_format(dev, vv->
ov_fmt->trans);
658 saa7146_set_clipping_rect(fh);
670 saa7146_disable_clipping(dev);
678 if( which < 1 || which > 3) {
683 where = (which-1)*0x18;
711 int width = buf->
fmt->width;
712 int height = buf->
fmt->height;
718 DEB_CAP(
"[size=%dx%d,fields=%s]\n",
721 if( bytesperline != 0) {
722 vdma1.pitch = bytesperline*2;
724 vdma1.pitch = (width*depth*2)/8;
726 vdma1.num_line_byte = ((vv->
standard->v_field<<16) + vv->
standard->h_pixels);
727 vdma1.base_page = buf->
pt[0].dma |
ME1 | sfmt->
swap;
729 if( 0 != vv->
vflip ) {
730 vdma1.prot_addr = buf->
pt[0].offset;
731 vdma1.base_even = buf->
pt[0].offset+(vdma1.pitch/2)*height;
732 vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2);
734 vdma1.base_even = buf->
pt[0].offset;
735 vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2);
736 vdma1.prot_addr = buf->
pt[0].offset+(vdma1.pitch/2)*height;
743 vdma1.base_odd = vdma1.prot_addr;
746 vdma1.base_odd = vdma1.base_even;
747 vdma1.base_even = vdma1.prot_addr;
751 vdma1.base_odd = vdma1.prot_addr;
754 vdma1.base_odd = vdma1.base_even;
755 vdma1.base_even = vdma1.prot_addr;
759 if( 0 != vv->
vflip ) {
769 int height = buf->
fmt->height;
770 int width = buf->
fmt->width;
777 if( 0 != vv->
vflip ) {
800 int height = buf->
fmt->height;
801 int width = buf->
fmt->width;
803 vdma2->
pitch = width/2;
804 vdma3->
pitch = width/2;
806 if( 0 != vv->
vflip ) {
836 int width = buf->
fmt->width;
837 int height = buf->
fmt->height;
844 DEB_CAP(
"[size=%dx%d,fields=%s]\n",
853 vdma1.pitch = width*2;
854 vdma1.num_line_byte = ((vv->
standard->v_field<<16) + vv->
standard->h_pixels);
855 vdma1.base_page = buf->
pt[0].dma |
ME1;
857 if( 0 != vv->
vflip ) {
858 vdma1.prot_addr = buf->
pt[0].offset;
859 vdma1.base_even = ((vdma1.pitch/2)*height)+buf->
pt[0].offset;
860 vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2);
862 vdma1.base_even = buf->
pt[0].offset;
863 vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2);
864 vdma1.prot_addr = (vdma1.pitch/2)*height+buf->
pt[0].offset;
873 switch( sfmt->
depth ) {
875 calc_planar_420(vv,buf,&vdma2,&vdma3);
879 calc_planar_422(vv,buf,&vdma2,&vdma3);
890 vdma1.base_odd = vdma1.prot_addr;
897 vdma1.base_odd = vdma1.prot_addr;
904 vdma1.base_odd = vdma1.base_even;
905 vdma1.base_even = vdma1.prot_addr;
915 if( 0 != vv->
vflip ) {
932 static void program_capture_engine(
struct saa7146_dev *dev,
int planar)
1003 u32 vdma1_prot_addr;
1005 DEB_CAP(
"buf:%p, next:%p\n", buf, next);
1008 if( 0 == vdma1_prot_addr ) {
1010 DEB_CAP(
"forcing sync to new frame\n");
1014 saa7146_set_window(dev, buf->
fmt->width, buf->
fmt->height, buf->
fmt->field);
1015 saa7146_set_output_format(dev, sfmt->
trans);
1016 saa7146_disable_clipping(dev);
1026 calculate_video_dma_grab_planar(dev, buf);
1027 program_capture_engine(dev,1);
1029 calculate_video_dma_grab_packed(dev, buf);
1030 program_capture_engine(dev,0);