📄 saa7114.c
字号:
0xbe, 0x00, 0xbf, 0x00, 0xc0, 0x02, // Task B definition 0xc1, 0x08, 0xc2, 0x00, 0xc3, 0x40, 0xc4, 0x00, // window settings 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8, 0x00, 0xc9, 0x00, 0xca, 0x00, 0xcb, 0x00, 0xcc, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xcf, 0x00, 0xd0, 0x01, // horizontal integer prescaling ratio 0xd1, 0x00, // horizontal prescaler accumulation sequence length 0xd2, 0x00, // UV FIR filter, Y FIR filter, prescaler DC gain 0xd3, 0x00, 0xd4, 0x80, // luminance brightness 0xd5, 0x40, // luminance gain 0xd6, 0x40, // chrominance saturation 0xd7, 0x00, 0xd8, 0x00, // horizontal luminance scaling increment 0xd9, 0x04, 0xda, 0x00, // horizontal luminance phase offset 0xdb, 0x00, 0xdc, 0x00, // horizontal chrominance scaling increment 0xdd, 0x02, 0xde, 0x00, // horizontal chrominance phase offset 0xdf, 0x00, 0xe0, 0x00, // vertical luminance scaling increment 0xe1, 0x04, 0xe2, 0x00, // vertical chrominance scaling increment 0xe3, 0x04, 0xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0xe8, 0x00, 0xe9, 0x00, 0xea, 0x00, 0xeb, 0x00, 0xec, 0x00, 0xed, 0x00, 0xee, 0x00, 0xef, 0x00};static intsaa7114_command (struct i2c_client *client, unsigned int cmd, void *arg){ struct saa7114 *decoder = i2c_get_clientdata(client); switch (cmd) { case 0: //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client)); //saa7114_write_block(client, init, sizeof(init)); break; case DECODER_DUMP: { int i; dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client)); for (i = 0; i < 32; i += 16) { int j; printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); for (j = 0; j < 16; ++j) { printk(" %02x", saa7114_read(client, i + j)); } printk("\n"); } } break; case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n", I2C_NAME(client)); cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; cap->inputs = 8; cap->outputs = 1; } break; case DECODER_GET_STATUS: { int *iarg = arg; int status; int res; status = saa7114_read(client, 0x1f); dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), status); res = 0; if ((status & (1 << 6)) == 0) { res |= DECODER_STATUS_GOOD; } switch (decoder->norm) { case VIDEO_MODE_NTSC: res |= DECODER_STATUS_NTSC; break; case VIDEO_MODE_PAL: res |= DECODER_STATUS_PAL; break; case VIDEO_MODE_SECAM: res |= DECODER_STATUS_SECAM; break; default: case VIDEO_MODE_AUTO: if ((status & (1 << 5)) != 0) { res |= DECODER_STATUS_NTSC; } else { res |= DECODER_STATUS_PAL; } break; } if ((status & (1 << 0)) != 0) { res |= DECODER_STATUS_COLOR; } *iarg = res; } break; case DECODER_SET_NORM: { int *iarg = arg; short int hoff = 0, voff = 0, w = 0, h = 0; dprintk(1, KERN_DEBUG "%s: decoder set norm ", I2C_NAME(client)); switch (*iarg) { case VIDEO_MODE_NTSC: dprintk(1, "NTSC\n"); decoder->reg[REG_ADDR(0x06)] = SAA_7114_NTSC_HSYNC_START; decoder->reg[REG_ADDR(0x07)] = SAA_7114_NTSC_HSYNC_STOP; decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture decoder->reg[REG_ADDR(0x0e)] = 0x85; decoder->reg[REG_ADDR(0x0f)] = 0x24; hoff = SAA_7114_NTSC_HOFFSET; voff = SAA_7114_NTSC_VOFFSET; w = SAA_7114_NTSC_WIDTH; h = SAA_7114_NTSC_HEIGHT; break; case VIDEO_MODE_PAL: dprintk(1, "PAL\n"); decoder->reg[REG_ADDR(0x06)] = SAA_7114_PAL_HSYNC_START; decoder->reg[REG_ADDR(0x07)] = SAA_7114_PAL_HSYNC_STOP; decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture decoder->reg[REG_ADDR(0x0e)] = 0x81; decoder->reg[REG_ADDR(0x0f)] = 0x24; hoff = SAA_7114_PAL_HOFFSET; voff = SAA_7114_PAL_VOFFSET; w = SAA_7114_PAL_WIDTH; h = SAA_7114_PAL_HEIGHT; break; default: dprintk(1, " Unknown video mode!!!\n"); return -EINVAL; } decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off saa7114_write(client, 0x88, 0xd8); // sw reset scaler saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write_block(client, decoder->reg + (0x06 << 1), 3 << 1); saa7114_write_block(client, decoder->reg + (0x0e << 1), 2 << 1); saa7114_write_block(client, decoder->reg + (0x5a << 1), 2 << 1); saa7114_write_block(client, decoder->reg + (0x94 << 1), (0x9f + 1 - 0x94) << 1); saa7114_write_block(client, decoder->reg + (0xc4 << 1), (0xcf + 1 - 0xc4) << 1); saa7114_write(client, 0x88, 0xd8); // sw reset scaler saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection decoder->norm = *iarg; } break; case DECODER_SET_INPUT: { int *iarg = arg; dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n", I2C_NAME(client), *iarg); if (*iarg < 0 || *iarg > 7) { return -EINVAL; } if (decoder->input != *iarg) { dprintk(1, KERN_DEBUG "%s: now setting %s input\n", I2C_NAME(client), *iarg >= 6 ? "S-Video" : "Composite"); decoder->input = *iarg; /* select mode */ decoder->reg[REG_ADDR(0x02)] = (decoder-> reg[REG_ADDR(0x02)] & 0xf0) | (decoder-> input < 6 ? 0x0 : 0x9); saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]); /* bypass chrominance trap for modes 6..9 */ decoder->reg[REG_ADDR(0x09)] = (decoder-> reg[REG_ADDR(0x09)] & 0x7f) | (decoder-> input < 6 ? 0x0 : 0x80); saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]); decoder->reg[REG_ADDR(0x0e)] = decoder->input < 6 ? decoder-> reg[REG_ADDR(0x0e)] | 1 : decoder-> reg[REG_ADDR(0x0e)] & ~1; saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]); } } break; case DECODER_SET_OUTPUT: { int *iarg = arg; dprintk(1, KERN_DEBUG "%s: decoder set output\n", I2C_NAME(client)); /* not much choice of outputs */ if (*iarg != 0) { return -EINVAL; } } break; case DECODER_ENABLE_OUTPUT: { int *iarg = arg; int enable = (*iarg != 0); dprintk(1, KERN_DEBUG "%s: decoder %s output\n", I2C_NAME(client), enable ? "enable" : "disable"); decoder->playback = !enable; if (decoder->enable != enable) { decoder->enable = enable; /* RJ: If output should be disabled (for * playing videos), we also need a open PLL. * The input is set to 0 (where no input * source is connected), although this * is not necessary. * * If output should be enabled, we have to * reverse the above. */ if (decoder->enable) { decoder->reg[REG_ADDR(0x08)] = 0xb8; decoder->reg[REG_ADDR(0x12)] = 0xc9; decoder->reg[REG_ADDR(0x13)] = 0x80; decoder->reg[REG_ADDR(0x87)] = 0x01; } else { decoder->reg[REG_ADDR(0x08)] = 0x7c; decoder->reg[REG_ADDR(0x12)] = 0x00; decoder->reg[REG_ADDR(0x13)] = 0x00; decoder->reg[REG_ADDR(0x87)] = 0x00; } saa7114_write_block(client, decoder->reg + (0x12 << 1), 2 << 1); saa7114_write(client, 0x08, decoder->reg[REG_ADDR(0x08)]); saa7114_write(client, 0x87, decoder->reg[REG_ADDR(0x87)]); saa7114_write(client, 0x88, 0xd8); // sw reset scaler saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write(client, 0x80, 0x36); } } break; case DECODER_SET_PICTURE: { struct video_picture *pic = arg; dprintk(1, KERN_DEBUG "%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n", I2C_NAME(client), pic->brightness, pic->contrast, pic->colour, pic->hue); if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ decoder->bright = pic->brightness; saa7114_write(client, 0x0a, decoder->bright >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 127 we get 0-65535 */ decoder->contrast = pic->contrast; saa7114_write(client, 0x0b, decoder->contrast >> 9); } if (decoder->sat != pic->colour) { /* We want 0 to 127 we get 0-65535 */ decoder->sat = pic->colour; saa7114_write(client, 0x0c, decoder->sat >> 9); } if (decoder->hue != pic->hue) { /* We want -128 to 127 we get 0-65535 */ decoder->hue = pic->hue; saa7114_write(client, 0x0d, (decoder->hue - 32768) >> 8); } } break; default: return -EINVAL; } return 0;}/* ----------------------------------------------------------------------- *//* * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */static unsigned short normal_i2c[] = { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -