18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * saa717x - Philips SAA717xHL video decoder driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Based on the saa7115 driver 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Changes by Ohta Kyuma <alpha292@bremen.or.jp> 88c2ecf20Sopenharmony_ci * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004) 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Changes by T.Adachi (tadachi@tadachi-net.com) 118c2ecf20Sopenharmony_ci * - support audio, video scaler etc, and checked the initialize sequence. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl> 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Note: this is a reversed engineered driver based on captures from 168c2ecf20Sopenharmony_ci * the I2C bus under Windows. This chip is very similar to the saa7134, 178c2ecf20Sopenharmony_ci * though. Unfortunately, this driver is currently only working for NTSC. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <linux/module.h> 218c2ecf20Sopenharmony_ci#include <linux/kernel.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci#include <linux/sched.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <linux/videodev2.h> 268c2ecf20Sopenharmony_ci#include <linux/i2c.h> 278c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 288c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver"); 318c2ecf20Sopenharmony_ciMODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil"); 328c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic int debug; 358c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 368c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug level (0-1)"); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * Generic i2c probe 408c2ecf20Sopenharmony_ci * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistruct saa717x_state { 448c2ecf20Sopenharmony_ci struct v4l2_subdev sd; 458c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler hdl; 468c2ecf20Sopenharmony_ci v4l2_std_id std; 478c2ecf20Sopenharmony_ci int input; 488c2ecf20Sopenharmony_ci int enable; 498c2ecf20Sopenharmony_ci int radio; 508c2ecf20Sopenharmony_ci int playback; 518c2ecf20Sopenharmony_ci int audio; 528c2ecf20Sopenharmony_ci int tuner_audio_mode; 538c2ecf20Sopenharmony_ci int audio_main_mute; 548c2ecf20Sopenharmony_ci int audio_main_vol_r; 558c2ecf20Sopenharmony_ci int audio_main_vol_l; 568c2ecf20Sopenharmony_ci u16 audio_main_bass; 578c2ecf20Sopenharmony_ci u16 audio_main_treble; 588c2ecf20Sopenharmony_ci u16 audio_main_volume; 598c2ecf20Sopenharmony_ci u16 audio_main_balance; 608c2ecf20Sopenharmony_ci int audio_input; 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic inline struct saa717x_state *to_state(struct v4l2_subdev *sd) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci return container_of(sd, struct saa717x_state, sd); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* for audio mode */ 768c2ecf20Sopenharmony_ci#define TUNER_AUDIO_MONO 0 /* LL */ 778c2ecf20Sopenharmony_ci#define TUNER_AUDIO_STEREO 1 /* LR */ 788c2ecf20Sopenharmony_ci#define TUNER_AUDIO_LANG1 2 /* LL */ 798c2ecf20Sopenharmony_ci#define TUNER_AUDIO_LANG2 3 /* RR */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define SAA717X_NTSC_WIDTH (704) 828c2ecf20Sopenharmony_ci#define SAA717X_NTSC_HEIGHT (480) 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(sd); 898c2ecf20Sopenharmony_ci struct i2c_adapter *adap = client->adapter; 908c2ecf20Sopenharmony_ci int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488; 918c2ecf20Sopenharmony_ci unsigned char mm1[6]; 928c2ecf20Sopenharmony_ci struct i2c_msg msg; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci msg.flags = 0; 958c2ecf20Sopenharmony_ci msg.addr = client->addr; 968c2ecf20Sopenharmony_ci mm1[0] = (reg >> 8) & 0xff; 978c2ecf20Sopenharmony_ci mm1[1] = reg & 0xff; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (fw_addr) { 1008c2ecf20Sopenharmony_ci mm1[4] = (value >> 16) & 0xff; 1018c2ecf20Sopenharmony_ci mm1[3] = (value >> 8) & 0xff; 1028c2ecf20Sopenharmony_ci mm1[2] = value & 0xff; 1038c2ecf20Sopenharmony_ci } else { 1048c2ecf20Sopenharmony_ci mm1[2] = value & 0xff; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */ 1078c2ecf20Sopenharmony_ci msg.buf = mm1; 1088c2ecf20Sopenharmony_ci v4l2_dbg(2, debug, sd, "wrote: reg 0x%03x=%08x\n", reg, value); 1098c2ecf20Sopenharmony_ci return i2c_transfer(adap, &msg, 1) == 1; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci while (data[0] || data[1]) { 1158c2ecf20Sopenharmony_ci saa717x_write(sd, data[0], data[1]); 1168c2ecf20Sopenharmony_ci data += 2; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic u32 saa717x_read(struct v4l2_subdev *sd, u32 reg) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(sd); 1238c2ecf20Sopenharmony_ci struct i2c_adapter *adap = client->adapter; 1248c2ecf20Sopenharmony_ci int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528; 1258c2ecf20Sopenharmony_ci unsigned char mm1[2]; 1268c2ecf20Sopenharmony_ci unsigned char mm2[4] = { 0, 0, 0, 0 }; 1278c2ecf20Sopenharmony_ci struct i2c_msg msgs[2]; 1288c2ecf20Sopenharmony_ci u32 value; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci msgs[0].flags = 0; 1318c2ecf20Sopenharmony_ci msgs[1].flags = I2C_M_RD; 1328c2ecf20Sopenharmony_ci msgs[0].addr = msgs[1].addr = client->addr; 1338c2ecf20Sopenharmony_ci mm1[0] = (reg >> 8) & 0xff; 1348c2ecf20Sopenharmony_ci mm1[1] = reg & 0xff; 1358c2ecf20Sopenharmony_ci msgs[0].len = 2; 1368c2ecf20Sopenharmony_ci msgs[0].buf = mm1; 1378c2ecf20Sopenharmony_ci msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */ 1388c2ecf20Sopenharmony_ci msgs[1].buf = mm2; 1398c2ecf20Sopenharmony_ci i2c_transfer(adap, msgs, 2); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (fw_addr) 1428c2ecf20Sopenharmony_ci value = (mm2[2] << 16) | (mm2[1] << 8) | mm2[0]; 1438c2ecf20Sopenharmony_ci else 1448c2ecf20Sopenharmony_ci value = mm2[0]; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value); 1478c2ecf20Sopenharmony_ci return value; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic u32 reg_init_initialize[] = 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci /* from linux driver */ 1558c2ecf20Sopenharmony_ci 0x101, 0x008, /* Increment delay */ 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci 0x103, 0x000, /* Analog input control 2 */ 1588c2ecf20Sopenharmony_ci 0x104, 0x090, /* Analog input control 3 */ 1598c2ecf20Sopenharmony_ci 0x105, 0x090, /* Analog input control 4 */ 1608c2ecf20Sopenharmony_ci 0x106, 0x0eb, /* Horizontal sync start */ 1618c2ecf20Sopenharmony_ci 0x107, 0x0e0, /* Horizontal sync stop */ 1628c2ecf20Sopenharmony_ci 0x109, 0x055, /* Luminance control */ 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci 0x10f, 0x02a, /* Chroma gain control */ 1658c2ecf20Sopenharmony_ci 0x110, 0x000, /* Chroma control 2 */ 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci 0x114, 0x045, /* analog/ADC */ 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci 0x118, 0x040, /* RAW data gain */ 1708c2ecf20Sopenharmony_ci 0x119, 0x080, /* RAW data offset */ 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci 0x044, 0x000, /* VBI horizontal input window start (L) TASK A */ 1738c2ecf20Sopenharmony_ci 0x045, 0x000, /* VBI horizontal input window start (H) TASK A */ 1748c2ecf20Sopenharmony_ci 0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */ 1758c2ecf20Sopenharmony_ci 0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */ 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci 0x049, 0x000, /* VBI vertical input window start (H) TASK A */ 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci 0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */ 1808c2ecf20Sopenharmony_ci 0x04d, 0x002, /* VBI horizontal output length (H) TASK A */ 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci 0x064, 0x080, /* Lumina brightness TASK A */ 1838c2ecf20Sopenharmony_ci 0x065, 0x040, /* Luminance contrast TASK A */ 1848c2ecf20Sopenharmony_ci 0x066, 0x040, /* Chroma saturation TASK A */ 1858c2ecf20Sopenharmony_ci /* 067H: Reserved */ 1868c2ecf20Sopenharmony_ci 0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */ 1878c2ecf20Sopenharmony_ci 0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */ 1888c2ecf20Sopenharmony_ci 0x06a, 0x000, /* VBI phase offset TASK A */ 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci 0x06e, 0x000, /* Horizontal phase offset Luma TASK A */ 1918c2ecf20Sopenharmony_ci 0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */ 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci 0x072, 0x000, /* Vertical filter mode TASK A */ 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci 0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */ 1968c2ecf20Sopenharmony_ci 0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */ 1978c2ecf20Sopenharmony_ci 0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */ 1988c2ecf20Sopenharmony_ci 0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */ 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci 0x089, 0x000, /* VBI vertical input window start (H) TAKS B */ 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci 0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */ 2038c2ecf20Sopenharmony_ci 0x08d, 0x002, /* VBI horizontal output length (H) TASK B */ 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci 0x0a4, 0x080, /* Lumina brightness TASK B */ 2068c2ecf20Sopenharmony_ci 0x0a5, 0x040, /* Luminance contrast TASK B */ 2078c2ecf20Sopenharmony_ci 0x0a6, 0x040, /* Chroma saturation TASK B */ 2088c2ecf20Sopenharmony_ci /* 0A7H reserved */ 2098c2ecf20Sopenharmony_ci 0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */ 2108c2ecf20Sopenharmony_ci 0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */ 2118c2ecf20Sopenharmony_ci 0x0aa, 0x000, /* VBI phase offset TASK B */ 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci 0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */ 2148c2ecf20Sopenharmony_ci 0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */ 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci 0x0b2, 0x000, /* Vertical filter mode TASK B */ 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci 0x00c, 0x000, /* Start point GREEN path */ 2198c2ecf20Sopenharmony_ci 0x00d, 0x000, /* Start point BLUE path */ 2208c2ecf20Sopenharmony_ci 0x00e, 0x000, /* Start point RED path */ 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci 0x010, 0x010, /* GREEN path gamma curve --- */ 2238c2ecf20Sopenharmony_ci 0x011, 0x020, 2248c2ecf20Sopenharmony_ci 0x012, 0x030, 2258c2ecf20Sopenharmony_ci 0x013, 0x040, 2268c2ecf20Sopenharmony_ci 0x014, 0x050, 2278c2ecf20Sopenharmony_ci 0x015, 0x060, 2288c2ecf20Sopenharmony_ci 0x016, 0x070, 2298c2ecf20Sopenharmony_ci 0x017, 0x080, 2308c2ecf20Sopenharmony_ci 0x018, 0x090, 2318c2ecf20Sopenharmony_ci 0x019, 0x0a0, 2328c2ecf20Sopenharmony_ci 0x01a, 0x0b0, 2338c2ecf20Sopenharmony_ci 0x01b, 0x0c0, 2348c2ecf20Sopenharmony_ci 0x01c, 0x0d0, 2358c2ecf20Sopenharmony_ci 0x01d, 0x0e0, 2368c2ecf20Sopenharmony_ci 0x01e, 0x0f0, 2378c2ecf20Sopenharmony_ci 0x01f, 0x0ff, /* --- GREEN path gamma curve */ 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci 0x020, 0x010, /* BLUE path gamma curve --- */ 2408c2ecf20Sopenharmony_ci 0x021, 0x020, 2418c2ecf20Sopenharmony_ci 0x022, 0x030, 2428c2ecf20Sopenharmony_ci 0x023, 0x040, 2438c2ecf20Sopenharmony_ci 0x024, 0x050, 2448c2ecf20Sopenharmony_ci 0x025, 0x060, 2458c2ecf20Sopenharmony_ci 0x026, 0x070, 2468c2ecf20Sopenharmony_ci 0x027, 0x080, 2478c2ecf20Sopenharmony_ci 0x028, 0x090, 2488c2ecf20Sopenharmony_ci 0x029, 0x0a0, 2498c2ecf20Sopenharmony_ci 0x02a, 0x0b0, 2508c2ecf20Sopenharmony_ci 0x02b, 0x0c0, 2518c2ecf20Sopenharmony_ci 0x02c, 0x0d0, 2528c2ecf20Sopenharmony_ci 0x02d, 0x0e0, 2538c2ecf20Sopenharmony_ci 0x02e, 0x0f0, 2548c2ecf20Sopenharmony_ci 0x02f, 0x0ff, /* --- BLUE path gamma curve */ 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci 0x030, 0x010, /* RED path gamma curve --- */ 2578c2ecf20Sopenharmony_ci 0x031, 0x020, 2588c2ecf20Sopenharmony_ci 0x032, 0x030, 2598c2ecf20Sopenharmony_ci 0x033, 0x040, 2608c2ecf20Sopenharmony_ci 0x034, 0x050, 2618c2ecf20Sopenharmony_ci 0x035, 0x060, 2628c2ecf20Sopenharmony_ci 0x036, 0x070, 2638c2ecf20Sopenharmony_ci 0x037, 0x080, 2648c2ecf20Sopenharmony_ci 0x038, 0x090, 2658c2ecf20Sopenharmony_ci 0x039, 0x0a0, 2668c2ecf20Sopenharmony_ci 0x03a, 0x0b0, 2678c2ecf20Sopenharmony_ci 0x03b, 0x0c0, 2688c2ecf20Sopenharmony_ci 0x03c, 0x0d0, 2698c2ecf20Sopenharmony_ci 0x03d, 0x0e0, 2708c2ecf20Sopenharmony_ci 0x03e, 0x0f0, 2718c2ecf20Sopenharmony_ci 0x03f, 0x0ff, /* --- RED path gamma curve */ 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci 0x109, 0x085, /* Luminance control */ 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /**** from app start ****/ 2768c2ecf20Sopenharmony_ci 0x584, 0x000, /* AGC gain control */ 2778c2ecf20Sopenharmony_ci 0x585, 0x000, /* Program count */ 2788c2ecf20Sopenharmony_ci 0x586, 0x003, /* Status reset */ 2798c2ecf20Sopenharmony_ci 0x588, 0x0ff, /* Number of audio samples (L) */ 2808c2ecf20Sopenharmony_ci 0x589, 0x00f, /* Number of audio samples (M) */ 2818c2ecf20Sopenharmony_ci 0x58a, 0x000, /* Number of audio samples (H) */ 2828c2ecf20Sopenharmony_ci 0x58b, 0x000, /* Audio select */ 2838c2ecf20Sopenharmony_ci 0x58c, 0x010, /* Audio channel assign1 */ 2848c2ecf20Sopenharmony_ci 0x58d, 0x032, /* Audio channel assign2 */ 2858c2ecf20Sopenharmony_ci 0x58e, 0x054, /* Audio channel assign3 */ 2868c2ecf20Sopenharmony_ci 0x58f, 0x023, /* Audio format */ 2878c2ecf20Sopenharmony_ci 0x590, 0x000, /* SIF control */ 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci 0x595, 0x000, /* ?? */ 2908c2ecf20Sopenharmony_ci 0x596, 0x000, /* ?? */ 2918c2ecf20Sopenharmony_ci 0x597, 0x000, /* ?? */ 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci 0x464, 0x00, /* Digital input crossbar1 */ 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci 0x46c, 0xbbbb10, /* Digital output selection1-3 */ 2968c2ecf20Sopenharmony_ci 0x470, 0x101010, /* Digital output selection4-6 */ 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci 0x478, 0x00, /* Sound feature control */ 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci 0x474, 0x18, /* Softmute control */ 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci 0x454, 0x0425b9, /* Sound Easy programming(reset) */ 3038c2ecf20Sopenharmony_ci 0x454, 0x042539, /* Sound Easy programming(reset) */ 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /**** common setting( of DVD play, including scaler commands) ****/ 3078c2ecf20Sopenharmony_ci 0x042, 0x003, /* Data path configuration for VBI (TASK A) */ 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci 0x082, 0x003, /* Data path configuration for VBI (TASK B) */ 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci 0x108, 0x0f8, /* Sync control */ 3128c2ecf20Sopenharmony_ci 0x2a9, 0x0fd, /* ??? */ 3138c2ecf20Sopenharmony_ci 0x102, 0x089, /* select video input "mode 9" */ 3148c2ecf20Sopenharmony_ci 0x111, 0x000, /* Mode/delay control */ 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci 0x10e, 0x00a, /* Chroma control 1 */ 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci 0x594, 0x002, /* SIF, analog I/O select */ 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci 0x454, 0x0425b9, /* Sound */ 3218c2ecf20Sopenharmony_ci 0x454, 0x042539, 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci 0x111, 0x000, 3248c2ecf20Sopenharmony_ci 0x10e, 0x00a, 3258c2ecf20Sopenharmony_ci 0x464, 0x000, 3268c2ecf20Sopenharmony_ci 0x300, 0x000, 3278c2ecf20Sopenharmony_ci 0x301, 0x006, 3288c2ecf20Sopenharmony_ci 0x302, 0x000, 3298c2ecf20Sopenharmony_ci 0x303, 0x006, 3308c2ecf20Sopenharmony_ci 0x308, 0x040, 3318c2ecf20Sopenharmony_ci 0x309, 0x000, 3328c2ecf20Sopenharmony_ci 0x30a, 0x000, 3338c2ecf20Sopenharmony_ci 0x30b, 0x000, 3348c2ecf20Sopenharmony_ci 0x000, 0x002, 3358c2ecf20Sopenharmony_ci 0x001, 0x000, 3368c2ecf20Sopenharmony_ci 0x002, 0x000, 3378c2ecf20Sopenharmony_ci 0x003, 0x000, 3388c2ecf20Sopenharmony_ci 0x004, 0x033, 3398c2ecf20Sopenharmony_ci 0x040, 0x01d, 3408c2ecf20Sopenharmony_ci 0x041, 0x001, 3418c2ecf20Sopenharmony_ci 0x042, 0x004, 3428c2ecf20Sopenharmony_ci 0x043, 0x000, 3438c2ecf20Sopenharmony_ci 0x080, 0x01e, 3448c2ecf20Sopenharmony_ci 0x081, 0x001, 3458c2ecf20Sopenharmony_ci 0x082, 0x004, 3468c2ecf20Sopenharmony_ci 0x083, 0x000, 3478c2ecf20Sopenharmony_ci 0x190, 0x018, 3488c2ecf20Sopenharmony_ci 0x115, 0x000, 3498c2ecf20Sopenharmony_ci 0x116, 0x012, 3508c2ecf20Sopenharmony_ci 0x117, 0x018, 3518c2ecf20Sopenharmony_ci 0x04a, 0x011, 3528c2ecf20Sopenharmony_ci 0x08a, 0x011, 3538c2ecf20Sopenharmony_ci 0x04b, 0x000, 3548c2ecf20Sopenharmony_ci 0x08b, 0x000, 3558c2ecf20Sopenharmony_ci 0x048, 0x000, 3568c2ecf20Sopenharmony_ci 0x088, 0x000, 3578c2ecf20Sopenharmony_ci 0x04e, 0x012, 3588c2ecf20Sopenharmony_ci 0x08e, 0x012, 3598c2ecf20Sopenharmony_ci 0x058, 0x012, 3608c2ecf20Sopenharmony_ci 0x098, 0x012, 3618c2ecf20Sopenharmony_ci 0x059, 0x000, 3628c2ecf20Sopenharmony_ci 0x099, 0x000, 3638c2ecf20Sopenharmony_ci 0x05a, 0x003, 3648c2ecf20Sopenharmony_ci 0x09a, 0x003, 3658c2ecf20Sopenharmony_ci 0x05b, 0x001, 3668c2ecf20Sopenharmony_ci 0x09b, 0x001, 3678c2ecf20Sopenharmony_ci 0x054, 0x008, 3688c2ecf20Sopenharmony_ci 0x094, 0x008, 3698c2ecf20Sopenharmony_ci 0x055, 0x000, 3708c2ecf20Sopenharmony_ci 0x095, 0x000, 3718c2ecf20Sopenharmony_ci 0x056, 0x0c7, 3728c2ecf20Sopenharmony_ci 0x096, 0x0c7, 3738c2ecf20Sopenharmony_ci 0x057, 0x002, 3748c2ecf20Sopenharmony_ci 0x097, 0x002, 3758c2ecf20Sopenharmony_ci 0x0ff, 0x0ff, 3768c2ecf20Sopenharmony_ci 0x060, 0x001, 3778c2ecf20Sopenharmony_ci 0x0a0, 0x001, 3788c2ecf20Sopenharmony_ci 0x061, 0x000, 3798c2ecf20Sopenharmony_ci 0x0a1, 0x000, 3808c2ecf20Sopenharmony_ci 0x062, 0x000, 3818c2ecf20Sopenharmony_ci 0x0a2, 0x000, 3828c2ecf20Sopenharmony_ci 0x063, 0x000, 3838c2ecf20Sopenharmony_ci 0x0a3, 0x000, 3848c2ecf20Sopenharmony_ci 0x070, 0x000, 3858c2ecf20Sopenharmony_ci 0x0b0, 0x000, 3868c2ecf20Sopenharmony_ci 0x071, 0x004, 3878c2ecf20Sopenharmony_ci 0x0b1, 0x004, 3888c2ecf20Sopenharmony_ci 0x06c, 0x0e9, 3898c2ecf20Sopenharmony_ci 0x0ac, 0x0e9, 3908c2ecf20Sopenharmony_ci 0x06d, 0x003, 3918c2ecf20Sopenharmony_ci 0x0ad, 0x003, 3928c2ecf20Sopenharmony_ci 0x05c, 0x0d0, 3938c2ecf20Sopenharmony_ci 0x09c, 0x0d0, 3948c2ecf20Sopenharmony_ci 0x05d, 0x002, 3958c2ecf20Sopenharmony_ci 0x09d, 0x002, 3968c2ecf20Sopenharmony_ci 0x05e, 0x0f2, 3978c2ecf20Sopenharmony_ci 0x09e, 0x0f2, 3988c2ecf20Sopenharmony_ci 0x05f, 0x000, 3998c2ecf20Sopenharmony_ci 0x09f, 0x000, 4008c2ecf20Sopenharmony_ci 0x074, 0x000, 4018c2ecf20Sopenharmony_ci 0x0b4, 0x000, 4028c2ecf20Sopenharmony_ci 0x075, 0x000, 4038c2ecf20Sopenharmony_ci 0x0b5, 0x000, 4048c2ecf20Sopenharmony_ci 0x076, 0x000, 4058c2ecf20Sopenharmony_ci 0x0b6, 0x000, 4068c2ecf20Sopenharmony_ci 0x077, 0x000, 4078c2ecf20Sopenharmony_ci 0x0b7, 0x000, 4088c2ecf20Sopenharmony_ci 0x195, 0x008, 4098c2ecf20Sopenharmony_ci 0x0ff, 0x0ff, 4108c2ecf20Sopenharmony_ci 0x108, 0x0f8, 4118c2ecf20Sopenharmony_ci 0x111, 0x000, 4128c2ecf20Sopenharmony_ci 0x10e, 0x00a, 4138c2ecf20Sopenharmony_ci 0x2a9, 0x0fd, 4148c2ecf20Sopenharmony_ci 0x464, 0x001, 4158c2ecf20Sopenharmony_ci 0x454, 0x042135, 4168c2ecf20Sopenharmony_ci 0x598, 0x0e7, 4178c2ecf20Sopenharmony_ci 0x599, 0x07d, 4188c2ecf20Sopenharmony_ci 0x59a, 0x018, 4198c2ecf20Sopenharmony_ci 0x59c, 0x066, 4208c2ecf20Sopenharmony_ci 0x59d, 0x090, 4218c2ecf20Sopenharmony_ci 0x59e, 0x001, 4228c2ecf20Sopenharmony_ci 0x584, 0x000, 4238c2ecf20Sopenharmony_ci 0x585, 0x000, 4248c2ecf20Sopenharmony_ci 0x586, 0x003, 4258c2ecf20Sopenharmony_ci 0x588, 0x0ff, 4268c2ecf20Sopenharmony_ci 0x589, 0x00f, 4278c2ecf20Sopenharmony_ci 0x58a, 0x000, 4288c2ecf20Sopenharmony_ci 0x58b, 0x000, 4298c2ecf20Sopenharmony_ci 0x58c, 0x010, 4308c2ecf20Sopenharmony_ci 0x58d, 0x032, 4318c2ecf20Sopenharmony_ci 0x58e, 0x054, 4328c2ecf20Sopenharmony_ci 0x58f, 0x023, 4338c2ecf20Sopenharmony_ci 0x590, 0x000, 4348c2ecf20Sopenharmony_ci 0x595, 0x000, 4358c2ecf20Sopenharmony_ci 0x596, 0x000, 4368c2ecf20Sopenharmony_ci 0x597, 0x000, 4378c2ecf20Sopenharmony_ci 0x464, 0x000, 4388c2ecf20Sopenharmony_ci 0x46c, 0xbbbb10, 4398c2ecf20Sopenharmony_ci 0x470, 0x101010, 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci 0x478, 0x000, 4438c2ecf20Sopenharmony_ci 0x474, 0x018, 4448c2ecf20Sopenharmony_ci 0x454, 0x042135, 4458c2ecf20Sopenharmony_ci 0x598, 0x0e7, 4468c2ecf20Sopenharmony_ci 0x599, 0x07d, 4478c2ecf20Sopenharmony_ci 0x59a, 0x018, 4488c2ecf20Sopenharmony_ci 0x59c, 0x066, 4498c2ecf20Sopenharmony_ci 0x59d, 0x090, 4508c2ecf20Sopenharmony_ci 0x59e, 0x001, 4518c2ecf20Sopenharmony_ci 0x584, 0x000, 4528c2ecf20Sopenharmony_ci 0x585, 0x000, 4538c2ecf20Sopenharmony_ci 0x586, 0x003, 4548c2ecf20Sopenharmony_ci 0x588, 0x0ff, 4558c2ecf20Sopenharmony_ci 0x589, 0x00f, 4568c2ecf20Sopenharmony_ci 0x58a, 0x000, 4578c2ecf20Sopenharmony_ci 0x58b, 0x000, 4588c2ecf20Sopenharmony_ci 0x58c, 0x010, 4598c2ecf20Sopenharmony_ci 0x58d, 0x032, 4608c2ecf20Sopenharmony_ci 0x58e, 0x054, 4618c2ecf20Sopenharmony_ci 0x58f, 0x023, 4628c2ecf20Sopenharmony_ci 0x590, 0x000, 4638c2ecf20Sopenharmony_ci 0x595, 0x000, 4648c2ecf20Sopenharmony_ci 0x596, 0x000, 4658c2ecf20Sopenharmony_ci 0x597, 0x000, 4668c2ecf20Sopenharmony_ci 0x464, 0x000, 4678c2ecf20Sopenharmony_ci 0x46c, 0xbbbb10, 4688c2ecf20Sopenharmony_ci 0x470, 0x101010, 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci 0x478, 0x000, 4718c2ecf20Sopenharmony_ci 0x474, 0x018, 4728c2ecf20Sopenharmony_ci 0x454, 0x042135, 4738c2ecf20Sopenharmony_ci 0x598, 0x0e7, 4748c2ecf20Sopenharmony_ci 0x599, 0x07d, 4758c2ecf20Sopenharmony_ci 0x59a, 0x018, 4768c2ecf20Sopenharmony_ci 0x59c, 0x066, 4778c2ecf20Sopenharmony_ci 0x59d, 0x090, 4788c2ecf20Sopenharmony_ci 0x59e, 0x001, 4798c2ecf20Sopenharmony_ci 0x584, 0x000, 4808c2ecf20Sopenharmony_ci 0x585, 0x000, 4818c2ecf20Sopenharmony_ci 0x586, 0x003, 4828c2ecf20Sopenharmony_ci 0x588, 0x0ff, 4838c2ecf20Sopenharmony_ci 0x589, 0x00f, 4848c2ecf20Sopenharmony_ci 0x58a, 0x000, 4858c2ecf20Sopenharmony_ci 0x58b, 0x000, 4868c2ecf20Sopenharmony_ci 0x58c, 0x010, 4878c2ecf20Sopenharmony_ci 0x58d, 0x032, 4888c2ecf20Sopenharmony_ci 0x58e, 0x054, 4898c2ecf20Sopenharmony_ci 0x58f, 0x023, 4908c2ecf20Sopenharmony_ci 0x590, 0x000, 4918c2ecf20Sopenharmony_ci 0x595, 0x000, 4928c2ecf20Sopenharmony_ci 0x596, 0x000, 4938c2ecf20Sopenharmony_ci 0x597, 0x000, 4948c2ecf20Sopenharmony_ci 0x464, 0x000, 4958c2ecf20Sopenharmony_ci 0x46c, 0xbbbb10, 4968c2ecf20Sopenharmony_ci 0x470, 0x101010, 4978c2ecf20Sopenharmony_ci 0x478, 0x000, 4988c2ecf20Sopenharmony_ci 0x474, 0x018, 4998c2ecf20Sopenharmony_ci 0x454, 0x042135, 5008c2ecf20Sopenharmony_ci 0x193, 0x000, 5018c2ecf20Sopenharmony_ci 0x300, 0x000, 5028c2ecf20Sopenharmony_ci 0x301, 0x006, 5038c2ecf20Sopenharmony_ci 0x302, 0x000, 5048c2ecf20Sopenharmony_ci 0x303, 0x006, 5058c2ecf20Sopenharmony_ci 0x308, 0x040, 5068c2ecf20Sopenharmony_ci 0x309, 0x000, 5078c2ecf20Sopenharmony_ci 0x30a, 0x000, 5088c2ecf20Sopenharmony_ci 0x30b, 0x000, 5098c2ecf20Sopenharmony_ci 0x000, 0x002, 5108c2ecf20Sopenharmony_ci 0x001, 0x000, 5118c2ecf20Sopenharmony_ci 0x002, 0x000, 5128c2ecf20Sopenharmony_ci 0x003, 0x000, 5138c2ecf20Sopenharmony_ci 0x004, 0x033, 5148c2ecf20Sopenharmony_ci 0x040, 0x01d, 5158c2ecf20Sopenharmony_ci 0x041, 0x001, 5168c2ecf20Sopenharmony_ci 0x042, 0x004, 5178c2ecf20Sopenharmony_ci 0x043, 0x000, 5188c2ecf20Sopenharmony_ci 0x080, 0x01e, 5198c2ecf20Sopenharmony_ci 0x081, 0x001, 5208c2ecf20Sopenharmony_ci 0x082, 0x004, 5218c2ecf20Sopenharmony_ci 0x083, 0x000, 5228c2ecf20Sopenharmony_ci 0x190, 0x018, 5238c2ecf20Sopenharmony_ci 0x115, 0x000, 5248c2ecf20Sopenharmony_ci 0x116, 0x012, 5258c2ecf20Sopenharmony_ci 0x117, 0x018, 5268c2ecf20Sopenharmony_ci 0x04a, 0x011, 5278c2ecf20Sopenharmony_ci 0x08a, 0x011, 5288c2ecf20Sopenharmony_ci 0x04b, 0x000, 5298c2ecf20Sopenharmony_ci 0x08b, 0x000, 5308c2ecf20Sopenharmony_ci 0x048, 0x000, 5318c2ecf20Sopenharmony_ci 0x088, 0x000, 5328c2ecf20Sopenharmony_ci 0x04e, 0x012, 5338c2ecf20Sopenharmony_ci 0x08e, 0x012, 5348c2ecf20Sopenharmony_ci 0x058, 0x012, 5358c2ecf20Sopenharmony_ci 0x098, 0x012, 5368c2ecf20Sopenharmony_ci 0x059, 0x000, 5378c2ecf20Sopenharmony_ci 0x099, 0x000, 5388c2ecf20Sopenharmony_ci 0x05a, 0x003, 5398c2ecf20Sopenharmony_ci 0x09a, 0x003, 5408c2ecf20Sopenharmony_ci 0x05b, 0x001, 5418c2ecf20Sopenharmony_ci 0x09b, 0x001, 5428c2ecf20Sopenharmony_ci 0x054, 0x008, 5438c2ecf20Sopenharmony_ci 0x094, 0x008, 5448c2ecf20Sopenharmony_ci 0x055, 0x000, 5458c2ecf20Sopenharmony_ci 0x095, 0x000, 5468c2ecf20Sopenharmony_ci 0x056, 0x0c7, 5478c2ecf20Sopenharmony_ci 0x096, 0x0c7, 5488c2ecf20Sopenharmony_ci 0x057, 0x002, 5498c2ecf20Sopenharmony_ci 0x097, 0x002, 5508c2ecf20Sopenharmony_ci 0x060, 0x001, 5518c2ecf20Sopenharmony_ci 0x0a0, 0x001, 5528c2ecf20Sopenharmony_ci 0x061, 0x000, 5538c2ecf20Sopenharmony_ci 0x0a1, 0x000, 5548c2ecf20Sopenharmony_ci 0x062, 0x000, 5558c2ecf20Sopenharmony_ci 0x0a2, 0x000, 5568c2ecf20Sopenharmony_ci 0x063, 0x000, 5578c2ecf20Sopenharmony_ci 0x0a3, 0x000, 5588c2ecf20Sopenharmony_ci 0x070, 0x000, 5598c2ecf20Sopenharmony_ci 0x0b0, 0x000, 5608c2ecf20Sopenharmony_ci 0x071, 0x004, 5618c2ecf20Sopenharmony_ci 0x0b1, 0x004, 5628c2ecf20Sopenharmony_ci 0x06c, 0x0e9, 5638c2ecf20Sopenharmony_ci 0x0ac, 0x0e9, 5648c2ecf20Sopenharmony_ci 0x06d, 0x003, 5658c2ecf20Sopenharmony_ci 0x0ad, 0x003, 5668c2ecf20Sopenharmony_ci 0x05c, 0x0d0, 5678c2ecf20Sopenharmony_ci 0x09c, 0x0d0, 5688c2ecf20Sopenharmony_ci 0x05d, 0x002, 5698c2ecf20Sopenharmony_ci 0x09d, 0x002, 5708c2ecf20Sopenharmony_ci 0x05e, 0x0f2, 5718c2ecf20Sopenharmony_ci 0x09e, 0x0f2, 5728c2ecf20Sopenharmony_ci 0x05f, 0x000, 5738c2ecf20Sopenharmony_ci 0x09f, 0x000, 5748c2ecf20Sopenharmony_ci 0x074, 0x000, 5758c2ecf20Sopenharmony_ci 0x0b4, 0x000, 5768c2ecf20Sopenharmony_ci 0x075, 0x000, 5778c2ecf20Sopenharmony_ci 0x0b5, 0x000, 5788c2ecf20Sopenharmony_ci 0x076, 0x000, 5798c2ecf20Sopenharmony_ci 0x0b6, 0x000, 5808c2ecf20Sopenharmony_ci 0x077, 0x000, 5818c2ecf20Sopenharmony_ci 0x0b7, 0x000, 5828c2ecf20Sopenharmony_ci 0x195, 0x008, 5838c2ecf20Sopenharmony_ci 0x598, 0x0e7, 5848c2ecf20Sopenharmony_ci 0x599, 0x07d, 5858c2ecf20Sopenharmony_ci 0x59a, 0x018, 5868c2ecf20Sopenharmony_ci 0x59c, 0x066, 5878c2ecf20Sopenharmony_ci 0x59d, 0x090, 5888c2ecf20Sopenharmony_ci 0x59e, 0x001, 5898c2ecf20Sopenharmony_ci 0x584, 0x000, 5908c2ecf20Sopenharmony_ci 0x585, 0x000, 5918c2ecf20Sopenharmony_ci 0x586, 0x003, 5928c2ecf20Sopenharmony_ci 0x588, 0x0ff, 5938c2ecf20Sopenharmony_ci 0x589, 0x00f, 5948c2ecf20Sopenharmony_ci 0x58a, 0x000, 5958c2ecf20Sopenharmony_ci 0x58b, 0x000, 5968c2ecf20Sopenharmony_ci 0x58c, 0x010, 5978c2ecf20Sopenharmony_ci 0x58d, 0x032, 5988c2ecf20Sopenharmony_ci 0x58e, 0x054, 5998c2ecf20Sopenharmony_ci 0x58f, 0x023, 6008c2ecf20Sopenharmony_ci 0x590, 0x000, 6018c2ecf20Sopenharmony_ci 0x595, 0x000, 6028c2ecf20Sopenharmony_ci 0x596, 0x000, 6038c2ecf20Sopenharmony_ci 0x597, 0x000, 6048c2ecf20Sopenharmony_ci 0x464, 0x000, 6058c2ecf20Sopenharmony_ci 0x46c, 0xbbbb10, 6068c2ecf20Sopenharmony_ci 0x470, 0x101010, 6078c2ecf20Sopenharmony_ci 0x478, 0x000, 6088c2ecf20Sopenharmony_ci 0x474, 0x018, 6098c2ecf20Sopenharmony_ci 0x454, 0x042135, 6108c2ecf20Sopenharmony_ci 0x193, 0x0a6, 6118c2ecf20Sopenharmony_ci 0x108, 0x0f8, 6128c2ecf20Sopenharmony_ci 0x042, 0x003, 6138c2ecf20Sopenharmony_ci 0x082, 0x003, 6148c2ecf20Sopenharmony_ci 0x454, 0x0425b9, 6158c2ecf20Sopenharmony_ci 0x454, 0x042539, 6168c2ecf20Sopenharmony_ci 0x193, 0x000, 6178c2ecf20Sopenharmony_ci 0x193, 0x0a6, 6188c2ecf20Sopenharmony_ci 0x464, 0x000, 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci 0, 0 6218c2ecf20Sopenharmony_ci}; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci/* Tuner */ 6248c2ecf20Sopenharmony_cistatic u32 reg_init_tuner_input[] = { 6258c2ecf20Sopenharmony_ci 0x108, 0x0f8, /* Sync control */ 6268c2ecf20Sopenharmony_ci 0x111, 0x000, /* Mode/delay control */ 6278c2ecf20Sopenharmony_ci 0x10e, 0x00a, /* Chroma control 1 */ 6288c2ecf20Sopenharmony_ci 0, 0 6298c2ecf20Sopenharmony_ci}; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci/* Composite */ 6328c2ecf20Sopenharmony_cistatic u32 reg_init_composite_input[] = { 6338c2ecf20Sopenharmony_ci 0x108, 0x0e8, /* Sync control */ 6348c2ecf20Sopenharmony_ci 0x111, 0x000, /* Mode/delay control */ 6358c2ecf20Sopenharmony_ci 0x10e, 0x04a, /* Chroma control 1 */ 6368c2ecf20Sopenharmony_ci 0, 0 6378c2ecf20Sopenharmony_ci}; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci/* S-Video */ 6408c2ecf20Sopenharmony_cistatic u32 reg_init_svideo_input[] = { 6418c2ecf20Sopenharmony_ci 0x108, 0x0e8, /* Sync control */ 6428c2ecf20Sopenharmony_ci 0x111, 0x000, /* Mode/delay control */ 6438c2ecf20Sopenharmony_ci 0x10e, 0x04a, /* Chroma control 1 */ 6448c2ecf20Sopenharmony_ci 0, 0 6458c2ecf20Sopenharmony_ci}; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic u32 reg_set_audio_template[4][2] = 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci { /* for MONO 6508c2ecf20Sopenharmony_ci tadachi 6/29 DMA audio output select? 6518c2ecf20Sopenharmony_ci Register 0x46c 6528c2ecf20Sopenharmony_ci 7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1 6538c2ecf20Sopenharmony_ci 0: MAIN left, 1: MAIN right 6548c2ecf20Sopenharmony_ci 2: AUX1 left, 3: AUX1 right 6558c2ecf20Sopenharmony_ci 4: AUX2 left, 5: AUX2 right 6568c2ecf20Sopenharmony_ci 6: DPL left, 7: DPL right 6578c2ecf20Sopenharmony_ci 8: DPL center, 9: DPL surround 6588c2ecf20Sopenharmony_ci A: monitor output, B: digital sense */ 6598c2ecf20Sopenharmony_ci 0xbbbb00, 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci /* tadachi 6/29 DAC and I2S output select? 6628c2ecf20Sopenharmony_ci Register 0x470 6638c2ecf20Sopenharmony_ci 7-4:DAC right ch. 3-0:DAC left ch. 6648c2ecf20Sopenharmony_ci I2S1 right,left I2S2 right,left */ 6658c2ecf20Sopenharmony_ci 0x00, 6668c2ecf20Sopenharmony_ci }, 6678c2ecf20Sopenharmony_ci { /* for STEREO */ 6688c2ecf20Sopenharmony_ci 0xbbbb10, 0x101010, 6698c2ecf20Sopenharmony_ci }, 6708c2ecf20Sopenharmony_ci { /* for LANG1 */ 6718c2ecf20Sopenharmony_ci 0xbbbb00, 0x00, 6728c2ecf20Sopenharmony_ci }, 6738c2ecf20Sopenharmony_ci { /* for LANG2/SAP */ 6748c2ecf20Sopenharmony_ci 0xbbbb11, 0x111111, 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci}; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci/* Get detected audio flags (from saa7134 driver) */ 6808c2ecf20Sopenharmony_cistatic void get_inf_dev_status(struct v4l2_subdev *sd, 6818c2ecf20Sopenharmony_ci int *dual_flag, int *stereo_flag) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci u32 reg_data3; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci static char *stdres[0x20] = { 6868c2ecf20Sopenharmony_ci [0x00] = "no standard detected", 6878c2ecf20Sopenharmony_ci [0x01] = "B/G (in progress)", 6888c2ecf20Sopenharmony_ci [0x02] = "D/K (in progress)", 6898c2ecf20Sopenharmony_ci [0x03] = "M (in progress)", 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci [0x04] = "B/G A2", 6928c2ecf20Sopenharmony_ci [0x05] = "B/G NICAM", 6938c2ecf20Sopenharmony_ci [0x06] = "D/K A2 (1)", 6948c2ecf20Sopenharmony_ci [0x07] = "D/K A2 (2)", 6958c2ecf20Sopenharmony_ci [0x08] = "D/K A2 (3)", 6968c2ecf20Sopenharmony_ci [0x09] = "D/K NICAM", 6978c2ecf20Sopenharmony_ci [0x0a] = "L NICAM", 6988c2ecf20Sopenharmony_ci [0x0b] = "I NICAM", 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci [0x0c] = "M Korea", 7018c2ecf20Sopenharmony_ci [0x0d] = "M BTSC ", 7028c2ecf20Sopenharmony_ci [0x0e] = "M EIAJ", 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci [0x0f] = "FM radio / IF 10.7 / 50 deemp", 7058c2ecf20Sopenharmony_ci [0x10] = "FM radio / IF 10.7 / 75 deemp", 7068c2ecf20Sopenharmony_ci [0x11] = "FM radio / IF sel / 50 deemp", 7078c2ecf20Sopenharmony_ci [0x12] = "FM radio / IF sel / 75 deemp", 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci [0x13 ... 0x1e] = "unknown", 7108c2ecf20Sopenharmony_ci [0x1f] = "??? [in progress]", 7118c2ecf20Sopenharmony_ci }; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci *dual_flag = *stereo_flag = 0; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci /* (demdec status: 0x528) */ 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci /* read current status */ 7198c2ecf20Sopenharmony_ci reg_data3 = saa717x_read(sd, 0x0528); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n", 7228c2ecf20Sopenharmony_ci reg_data3, stdres[reg_data3 & 0x1f], 7238c2ecf20Sopenharmony_ci (reg_data3 & 0x000020) ? ",stereo" : "", 7248c2ecf20Sopenharmony_ci (reg_data3 & 0x000040) ? ",dual" : ""); 7258c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "detailed status: " 7268c2ecf20Sopenharmony_ci "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n", 7278c2ecf20Sopenharmony_ci (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone " : "", 7288c2ecf20Sopenharmony_ci (reg_data3 & 0x000100) ? " A2/EIAJ dual " : "", 7298c2ecf20Sopenharmony_ci (reg_data3 & 0x000200) ? " A2/EIAJ stereo " : "", 7308c2ecf20Sopenharmony_ci (reg_data3 & 0x000400) ? " A2/EIAJ noise mute " : "", 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci (reg_data3 & 0x000800) ? " BTSC/FM radio pilot " : "", 7338c2ecf20Sopenharmony_ci (reg_data3 & 0x001000) ? " SAP carrier " : "", 7348c2ecf20Sopenharmony_ci (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "", 7358c2ecf20Sopenharmony_ci (reg_data3 & 0x004000) ? " SAP noise mute " : "", 7368c2ecf20Sopenharmony_ci (reg_data3 & 0x008000) ? " VDSP " : "", 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci (reg_data3 & 0x010000) ? " NICST " : "", 7398c2ecf20Sopenharmony_ci (reg_data3 & 0x020000) ? " NICDU " : "", 7408c2ecf20Sopenharmony_ci (reg_data3 & 0x040000) ? " NICAM muted " : "", 7418c2ecf20Sopenharmony_ci (reg_data3 & 0x080000) ? " NICAM reserve sound " : "", 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci (reg_data3 & 0x100000) ? " init done " : ""); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (reg_data3 & 0x000220) { 7468c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "ST!!!\n"); 7478c2ecf20Sopenharmony_ci *stereo_flag = 1; 7488c2ecf20Sopenharmony_ci } 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci if (reg_data3 & 0x000140) { 7518c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DUAL!!!\n"); 7528c2ecf20Sopenharmony_ci *dual_flag = 1; 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci} 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci/* regs write to set audio mode */ 7578c2ecf20Sopenharmony_cistatic void set_audio_mode(struct v4l2_subdev *sd, int audio_mode) 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n", 7608c2ecf20Sopenharmony_ci audio_mode); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]); 7638c2ecf20Sopenharmony_ci saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]); 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci/* write regs to set audio volume, bass and treble */ 7678c2ecf20Sopenharmony_cistatic int set_audio_regs(struct v4l2_subdev *sd, 7688c2ecf20Sopenharmony_ci struct saa717x_state *decoder) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci u8 mute = 0xac; /* -84 dB */ 7718c2ecf20Sopenharmony_ci u32 val; 7728c2ecf20Sopenharmony_ci unsigned int work_l, work_r; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci /* set SIF analog I/O select */ 7758c2ecf20Sopenharmony_ci saa717x_write(sd, 0x0594, decoder->audio_input); 7768c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "set audio input %d\n", 7778c2ecf20Sopenharmony_ci decoder->audio_input); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */ 7808c2ecf20Sopenharmony_ci work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768; 7818c2ecf20Sopenharmony_ci work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768; 7828c2ecf20Sopenharmony_ci decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40; 7838c2ecf20Sopenharmony_ci decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci /* set main volume */ 7868c2ecf20Sopenharmony_ci /* main volume L[7-0],R[7-0],0x00 24=24dB,-83dB, -84(mute) */ 7878c2ecf20Sopenharmony_ci /* def:0dB->6dB(MPG600GR) */ 7888c2ecf20Sopenharmony_ci /* if mute is on, set mute */ 7898c2ecf20Sopenharmony_ci if (decoder->audio_main_mute) { 7908c2ecf20Sopenharmony_ci val = mute | (mute << 8); 7918c2ecf20Sopenharmony_ci } else { 7928c2ecf20Sopenharmony_ci val = (u8)decoder->audio_main_vol_l | 7938c2ecf20Sopenharmony_ci ((u8)decoder->audio_main_vol_r << 8); 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci saa717x_write(sd, 0x480, val); 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci /* set bass and treble */ 7998c2ecf20Sopenharmony_ci val = decoder->audio_main_bass & 0x1f; 8008c2ecf20Sopenharmony_ci val |= (decoder->audio_main_treble & 0x1f) << 5; 8018c2ecf20Sopenharmony_ci saa717x_write(sd, 0x488, val); 8028c2ecf20Sopenharmony_ci return 0; 8038c2ecf20Sopenharmony_ci} 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci/********** scaling staff ***********/ 8068c2ecf20Sopenharmony_cistatic void set_h_prescale(struct v4l2_subdev *sd, 8078c2ecf20Sopenharmony_ci int task, int prescale) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci static const struct { 8108c2ecf20Sopenharmony_ci int xpsc; 8118c2ecf20Sopenharmony_ci int xacl; 8128c2ecf20Sopenharmony_ci int xc2_1; 8138c2ecf20Sopenharmony_ci int xdcg; 8148c2ecf20Sopenharmony_ci int vpfy; 8158c2ecf20Sopenharmony_ci } vals[] = { 8168c2ecf20Sopenharmony_ci /* XPSC XACL XC2_1 XDCG VPFY */ 8178c2ecf20Sopenharmony_ci { 1, 0, 0, 0, 0 }, 8188c2ecf20Sopenharmony_ci { 2, 2, 1, 2, 2 }, 8198c2ecf20Sopenharmony_ci { 3, 4, 1, 3, 2 }, 8208c2ecf20Sopenharmony_ci { 4, 8, 1, 4, 2 }, 8218c2ecf20Sopenharmony_ci { 5, 8, 1, 4, 2 }, 8228c2ecf20Sopenharmony_ci { 6, 8, 1, 4, 3 }, 8238c2ecf20Sopenharmony_ci { 7, 8, 1, 4, 3 }, 8248c2ecf20Sopenharmony_ci { 8, 15, 0, 4, 3 }, 8258c2ecf20Sopenharmony_ci { 9, 15, 0, 4, 3 }, 8268c2ecf20Sopenharmony_ci { 10, 16, 1, 5, 3 }, 8278c2ecf20Sopenharmony_ci }; 8288c2ecf20Sopenharmony_ci static const int count = ARRAY_SIZE(vals); 8298c2ecf20Sopenharmony_ci int i, task_shift; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci task_shift = task * 0x40; 8328c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) 8338c2ecf20Sopenharmony_ci if (vals[i].xpsc == prescale) 8348c2ecf20Sopenharmony_ci break; 8358c2ecf20Sopenharmony_ci if (i == count) 8368c2ecf20Sopenharmony_ci return; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* horizontal prescaling */ 8398c2ecf20Sopenharmony_ci saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc); 8408c2ecf20Sopenharmony_ci /* accumulation length */ 8418c2ecf20Sopenharmony_ci saa717x_write(sd, 0x61 + task_shift, vals[i].xacl); 8428c2ecf20Sopenharmony_ci /* level control */ 8438c2ecf20Sopenharmony_ci saa717x_write(sd, 0x62 + task_shift, 8448c2ecf20Sopenharmony_ci (vals[i].xc2_1 << 3) | vals[i].xdcg); 8458c2ecf20Sopenharmony_ci /*FIR prefilter control */ 8468c2ecf20Sopenharmony_ci saa717x_write(sd, 0x63 + task_shift, 8478c2ecf20Sopenharmony_ci (vals[i].vpfy << 2) | vals[i].vpfy); 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci/********** scaling staff ***********/ 8518c2ecf20Sopenharmony_cistatic void set_v_scale(struct v4l2_subdev *sd, int task, int yscale) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci int task_shift; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci task_shift = task * 0x40; 8568c2ecf20Sopenharmony_ci /* Vertical scaling ratio (LOW) */ 8578c2ecf20Sopenharmony_ci saa717x_write(sd, 0x70 + task_shift, yscale & 0xff); 8588c2ecf20Sopenharmony_ci /* Vertical scaling ratio (HI) */ 8598c2ecf20Sopenharmony_ci saa717x_write(sd, 0x71 + task_shift, yscale >> 8); 8608c2ecf20Sopenharmony_ci} 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_cistatic int saa717x_s_ctrl(struct v4l2_ctrl *ctrl) 8638c2ecf20Sopenharmony_ci{ 8648c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = to_sd(ctrl); 8658c2ecf20Sopenharmony_ci struct saa717x_state *state = to_state(sd); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci switch (ctrl->id) { 8688c2ecf20Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 8698c2ecf20Sopenharmony_ci saa717x_write(sd, 0x10a, ctrl->val); 8708c2ecf20Sopenharmony_ci return 0; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: 8738c2ecf20Sopenharmony_ci saa717x_write(sd, 0x10b, ctrl->val); 8748c2ecf20Sopenharmony_ci return 0; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: 8778c2ecf20Sopenharmony_ci saa717x_write(sd, 0x10c, ctrl->val); 8788c2ecf20Sopenharmony_ci return 0; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci case V4L2_CID_HUE: 8818c2ecf20Sopenharmony_ci saa717x_write(sd, 0x10d, ctrl->val); 8828c2ecf20Sopenharmony_ci return 0; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_MUTE: 8858c2ecf20Sopenharmony_ci state->audio_main_mute = ctrl->val; 8868c2ecf20Sopenharmony_ci break; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_VOLUME: 8898c2ecf20Sopenharmony_ci state->audio_main_volume = ctrl->val; 8908c2ecf20Sopenharmony_ci break; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BALANCE: 8938c2ecf20Sopenharmony_ci state->audio_main_balance = ctrl->val; 8948c2ecf20Sopenharmony_ci break; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_TREBLE: 8978c2ecf20Sopenharmony_ci state->audio_main_treble = ctrl->val; 8988c2ecf20Sopenharmony_ci break; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BASS: 9018c2ecf20Sopenharmony_ci state->audio_main_bass = ctrl->val; 9028c2ecf20Sopenharmony_ci break; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci default: 9058c2ecf20Sopenharmony_ci return 0; 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci set_audio_regs(sd, state); 9088c2ecf20Sopenharmony_ci return 0; 9098c2ecf20Sopenharmony_ci} 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_cistatic int saa717x_s_video_routing(struct v4l2_subdev *sd, 9128c2ecf20Sopenharmony_ci u32 input, u32 output, u32 config) 9138c2ecf20Sopenharmony_ci{ 9148c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 9158c2ecf20Sopenharmony_ci int is_tuner = input & 0x80; /* tuner input flag */ 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci input &= 0x7f; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input); 9208c2ecf20Sopenharmony_ci /* inputs from 0-9 are available*/ 9218c2ecf20Sopenharmony_ci /* saa717x have mode0-mode9 but mode5 is reserved. */ 9228c2ecf20Sopenharmony_ci if (input > 9 || input == 5) 9238c2ecf20Sopenharmony_ci return -EINVAL; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci if (decoder->input != input) { 9268c2ecf20Sopenharmony_ci int input_line = input; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci decoder->input = input_line; 9298c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "now setting %s input %d\n", 9308c2ecf20Sopenharmony_ci input_line >= 6 ? "S-Video" : "Composite", 9318c2ecf20Sopenharmony_ci input_line); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci /* select mode */ 9348c2ecf20Sopenharmony_ci saa717x_write(sd, 0x102, 9358c2ecf20Sopenharmony_ci (saa717x_read(sd, 0x102) & 0xf0) | 9368c2ecf20Sopenharmony_ci input_line); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci /* bypass chrominance trap for modes 6..9 */ 9398c2ecf20Sopenharmony_ci saa717x_write(sd, 0x109, 9408c2ecf20Sopenharmony_ci (saa717x_read(sd, 0x109) & 0x7f) | 9418c2ecf20Sopenharmony_ci (input_line < 6 ? 0x0 : 0x80)); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci /* change audio_mode */ 9448c2ecf20Sopenharmony_ci if (is_tuner) { 9458c2ecf20Sopenharmony_ci /* tuner */ 9468c2ecf20Sopenharmony_ci set_audio_mode(sd, decoder->tuner_audio_mode); 9478c2ecf20Sopenharmony_ci } else { 9488c2ecf20Sopenharmony_ci /* Force to STEREO mode if Composite or 9498c2ecf20Sopenharmony_ci * S-Video were chosen */ 9508c2ecf20Sopenharmony_ci set_audio_mode(sd, TUNER_AUDIO_STEREO); 9518c2ecf20Sopenharmony_ci } 9528c2ecf20Sopenharmony_ci /* change initialize procedure (Composite/S-Video) */ 9538c2ecf20Sopenharmony_ci if (is_tuner) 9548c2ecf20Sopenharmony_ci saa717x_write_regs(sd, reg_init_tuner_input); 9558c2ecf20Sopenharmony_ci else if (input_line >= 6) 9568c2ecf20Sopenharmony_ci saa717x_write_regs(sd, reg_init_svideo_input); 9578c2ecf20Sopenharmony_ci else 9588c2ecf20Sopenharmony_ci saa717x_write_regs(sd, reg_init_composite_input); 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci return 0; 9628c2ecf20Sopenharmony_ci} 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 9658c2ecf20Sopenharmony_cistatic int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 9668c2ecf20Sopenharmony_ci{ 9678c2ecf20Sopenharmony_ci reg->val = saa717x_read(sd, reg->reg); 9688c2ecf20Sopenharmony_ci reg->size = 1; 9698c2ecf20Sopenharmony_ci return 0; 9708c2ecf20Sopenharmony_ci} 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_cistatic int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) 9738c2ecf20Sopenharmony_ci{ 9748c2ecf20Sopenharmony_ci u16 addr = reg->reg & 0xffff; 9758c2ecf20Sopenharmony_ci u8 val = reg->val & 0xff; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci saa717x_write(sd, addr, val); 9788c2ecf20Sopenharmony_ci return 0; 9798c2ecf20Sopenharmony_ci} 9808c2ecf20Sopenharmony_ci#endif 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cistatic int saa717x_set_fmt(struct v4l2_subdev *sd, 9838c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 9848c2ecf20Sopenharmony_ci struct v4l2_subdev_format *format) 9858c2ecf20Sopenharmony_ci{ 9868c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt *fmt = &format->format; 9878c2ecf20Sopenharmony_ci int prescale, h_scale, v_scale; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "decoder set size\n"); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED) 9928c2ecf20Sopenharmony_ci return -EINVAL; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* FIXME need better bounds checking here */ 9958c2ecf20Sopenharmony_ci if (fmt->width < 1 || fmt->width > 1440) 9968c2ecf20Sopenharmony_ci return -EINVAL; 9978c2ecf20Sopenharmony_ci if (fmt->height < 1 || fmt->height > 960) 9988c2ecf20Sopenharmony_ci return -EINVAL; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci fmt->field = V4L2_FIELD_INTERLACED; 10018c2ecf20Sopenharmony_ci fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci if (format->which == V4L2_SUBDEV_FORMAT_TRY) 10048c2ecf20Sopenharmony_ci return 0; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci /* scaling setting */ 10078c2ecf20Sopenharmony_ci /* NTSC and interlace only */ 10088c2ecf20Sopenharmony_ci prescale = SAA717X_NTSC_WIDTH / fmt->width; 10098c2ecf20Sopenharmony_ci if (prescale == 0) 10108c2ecf20Sopenharmony_ci prescale = 1; 10118c2ecf20Sopenharmony_ci h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width; 10128c2ecf20Sopenharmony_ci /* interlace */ 10138c2ecf20Sopenharmony_ci v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height; 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci /* Horizontal prescaling etc */ 10168c2ecf20Sopenharmony_ci set_h_prescale(sd, 0, prescale); 10178c2ecf20Sopenharmony_ci set_h_prescale(sd, 1, prescale); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci /* Horizontal scaling increment */ 10208c2ecf20Sopenharmony_ci /* TASK A */ 10218c2ecf20Sopenharmony_ci saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF)); 10228c2ecf20Sopenharmony_ci saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF)); 10238c2ecf20Sopenharmony_ci /* TASK B */ 10248c2ecf20Sopenharmony_ci saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF)); 10258c2ecf20Sopenharmony_ci saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF)); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* Vertical prescaling etc */ 10288c2ecf20Sopenharmony_ci set_v_scale(sd, 0, v_scale); 10298c2ecf20Sopenharmony_ci set_v_scale(sd, 1, v_scale); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci /* set video output size */ 10328c2ecf20Sopenharmony_ci /* video number of pixels at output */ 10338c2ecf20Sopenharmony_ci /* TASK A */ 10348c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF)); 10358c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF)); 10368c2ecf20Sopenharmony_ci /* TASK B */ 10378c2ecf20Sopenharmony_ci saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF)); 10388c2ecf20Sopenharmony_ci saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF)); 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci /* video number of lines at output */ 10418c2ecf20Sopenharmony_ci /* TASK A */ 10428c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF)); 10438c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF)); 10448c2ecf20Sopenharmony_ci /* TASK B */ 10458c2ecf20Sopenharmony_ci saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF)); 10468c2ecf20Sopenharmony_ci saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF)); 10478c2ecf20Sopenharmony_ci return 0; 10488c2ecf20Sopenharmony_ci} 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_cistatic int saa717x_s_radio(struct v4l2_subdev *sd) 10518c2ecf20Sopenharmony_ci{ 10528c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci decoder->radio = 1; 10558c2ecf20Sopenharmony_ci return 0; 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 10598c2ecf20Sopenharmony_ci{ 10608c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "decoder set norm "); 10638c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "(not yet implemented)\n"); 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci decoder->radio = 0; 10668c2ecf20Sopenharmony_ci decoder->std = std; 10678c2ecf20Sopenharmony_ci return 0; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic int saa717x_s_audio_routing(struct v4l2_subdev *sd, 10718c2ecf20Sopenharmony_ci u32 input, u32 output, u32 config) 10728c2ecf20Sopenharmony_ci{ 10738c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci if (input < 3) { /* FIXME! --tadachi */ 10768c2ecf20Sopenharmony_ci decoder->audio_input = input; 10778c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, 10788c2ecf20Sopenharmony_ci "set decoder audio input to %d\n", 10798c2ecf20Sopenharmony_ci decoder->audio_input); 10808c2ecf20Sopenharmony_ci set_audio_regs(sd, decoder); 10818c2ecf20Sopenharmony_ci return 0; 10828c2ecf20Sopenharmony_ci } 10838c2ecf20Sopenharmony_ci return -ERANGE; 10848c2ecf20Sopenharmony_ci} 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_cistatic int saa717x_s_stream(struct v4l2_subdev *sd, int enable) 10878c2ecf20Sopenharmony_ci{ 10888c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "decoder %s output\n", 10918c2ecf20Sopenharmony_ci enable ? "enable" : "disable"); 10928c2ecf20Sopenharmony_ci decoder->enable = enable; 10938c2ecf20Sopenharmony_ci saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26); 10948c2ecf20Sopenharmony_ci return 0; 10958c2ecf20Sopenharmony_ci} 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci/* change audio mode */ 10988c2ecf20Sopenharmony_cistatic int saa717x_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 11018c2ecf20Sopenharmony_ci int audio_mode; 11028c2ecf20Sopenharmony_ci char *mes[4] = { 11038c2ecf20Sopenharmony_ci "MONO", "STEREO", "LANG1", "LANG2/SAP" 11048c2ecf20Sopenharmony_ci }; 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci audio_mode = TUNER_AUDIO_STEREO; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci switch (vt->audmode) { 11098c2ecf20Sopenharmony_ci case V4L2_TUNER_MODE_MONO: 11108c2ecf20Sopenharmony_ci audio_mode = TUNER_AUDIO_MONO; 11118c2ecf20Sopenharmony_ci break; 11128c2ecf20Sopenharmony_ci case V4L2_TUNER_MODE_STEREO: 11138c2ecf20Sopenharmony_ci audio_mode = TUNER_AUDIO_STEREO; 11148c2ecf20Sopenharmony_ci break; 11158c2ecf20Sopenharmony_ci case V4L2_TUNER_MODE_LANG2: 11168c2ecf20Sopenharmony_ci audio_mode = TUNER_AUDIO_LANG2; 11178c2ecf20Sopenharmony_ci break; 11188c2ecf20Sopenharmony_ci case V4L2_TUNER_MODE_LANG1: 11198c2ecf20Sopenharmony_ci audio_mode = TUNER_AUDIO_LANG1; 11208c2ecf20Sopenharmony_ci break; 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "change audio mode to %s\n", 11248c2ecf20Sopenharmony_ci mes[audio_mode]); 11258c2ecf20Sopenharmony_ci decoder->tuner_audio_mode = audio_mode; 11268c2ecf20Sopenharmony_ci /* The registers are not changed here. */ 11278c2ecf20Sopenharmony_ci /* See DECODER_ENABLE_OUTPUT section. */ 11288c2ecf20Sopenharmony_ci set_audio_mode(sd, decoder->tuner_audio_mode); 11298c2ecf20Sopenharmony_ci return 0; 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_cistatic int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) 11338c2ecf20Sopenharmony_ci{ 11348c2ecf20Sopenharmony_ci struct saa717x_state *decoder = to_state(sd); 11358c2ecf20Sopenharmony_ci int dual_f, stereo_f; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci if (decoder->radio) 11388c2ecf20Sopenharmony_ci return 0; 11398c2ecf20Sopenharmony_ci get_inf_dev_status(sd, &dual_f, &stereo_f); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n", 11428c2ecf20Sopenharmony_ci stereo_f, dual_f); 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci /* mono */ 11458c2ecf20Sopenharmony_ci if ((dual_f == 0) && (stereo_f == 0)) { 11468c2ecf20Sopenharmony_ci vt->rxsubchans = V4L2_TUNER_SUB_MONO; 11478c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DETECT==MONO\n"); 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci /* stereo */ 11518c2ecf20Sopenharmony_ci if (stereo_f == 1) { 11528c2ecf20Sopenharmony_ci if (vt->audmode == V4L2_TUNER_MODE_STEREO || 11538c2ecf20Sopenharmony_ci vt->audmode == V4L2_TUNER_MODE_LANG1) { 11548c2ecf20Sopenharmony_ci vt->rxsubchans = V4L2_TUNER_SUB_STEREO; 11558c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n"); 11568c2ecf20Sopenharmony_ci } else { 11578c2ecf20Sopenharmony_ci vt->rxsubchans = V4L2_TUNER_SUB_MONO; 11588c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n"); 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci /* dual */ 11638c2ecf20Sopenharmony_ci if (dual_f == 1) { 11648c2ecf20Sopenharmony_ci if (vt->audmode == V4L2_TUNER_MODE_LANG2) { 11658c2ecf20Sopenharmony_ci vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO; 11668c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n"); 11678c2ecf20Sopenharmony_ci } else { 11688c2ecf20Sopenharmony_ci vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO; 11698c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n"); 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci } 11728c2ecf20Sopenharmony_ci return 0; 11738c2ecf20Sopenharmony_ci} 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_cistatic int saa717x_log_status(struct v4l2_subdev *sd) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci struct saa717x_state *state = to_state(sd); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci v4l2_ctrl_handler_log_status(&state->hdl, sd->name); 11808c2ecf20Sopenharmony_ci return 0; 11818c2ecf20Sopenharmony_ci} 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops saa717x_ctrl_ops = { 11868c2ecf20Sopenharmony_ci .s_ctrl = saa717x_s_ctrl, 11878c2ecf20Sopenharmony_ci}; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_core_ops saa717x_core_ops = { 11908c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 11918c2ecf20Sopenharmony_ci .g_register = saa717x_g_register, 11928c2ecf20Sopenharmony_ci .s_register = saa717x_s_register, 11938c2ecf20Sopenharmony_ci#endif 11948c2ecf20Sopenharmony_ci .log_status = saa717x_log_status, 11958c2ecf20Sopenharmony_ci}; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = { 11988c2ecf20Sopenharmony_ci .g_tuner = saa717x_g_tuner, 11998c2ecf20Sopenharmony_ci .s_tuner = saa717x_s_tuner, 12008c2ecf20Sopenharmony_ci .s_radio = saa717x_s_radio, 12018c2ecf20Sopenharmony_ci}; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_video_ops saa717x_video_ops = { 12048c2ecf20Sopenharmony_ci .s_std = saa717x_s_std, 12058c2ecf20Sopenharmony_ci .s_routing = saa717x_s_video_routing, 12068c2ecf20Sopenharmony_ci .s_stream = saa717x_s_stream, 12078c2ecf20Sopenharmony_ci}; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_audio_ops saa717x_audio_ops = { 12108c2ecf20Sopenharmony_ci .s_routing = saa717x_s_audio_routing, 12118c2ecf20Sopenharmony_ci}; 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_pad_ops saa717x_pad_ops = { 12148c2ecf20Sopenharmony_ci .set_fmt = saa717x_set_fmt, 12158c2ecf20Sopenharmony_ci}; 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_ops saa717x_ops = { 12188c2ecf20Sopenharmony_ci .core = &saa717x_core_ops, 12198c2ecf20Sopenharmony_ci .tuner = &saa717x_tuner_ops, 12208c2ecf20Sopenharmony_ci .audio = &saa717x_audio_ops, 12218c2ecf20Sopenharmony_ci .video = &saa717x_video_ops, 12228c2ecf20Sopenharmony_ci .pad = &saa717x_pad_ops, 12238c2ecf20Sopenharmony_ci}; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci/* i2c implementation */ 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 12318c2ecf20Sopenharmony_cistatic int saa717x_probe(struct i2c_client *client, 12328c2ecf20Sopenharmony_ci const struct i2c_device_id *did) 12338c2ecf20Sopenharmony_ci{ 12348c2ecf20Sopenharmony_ci struct saa717x_state *decoder; 12358c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl; 12368c2ecf20Sopenharmony_ci struct v4l2_subdev *sd; 12378c2ecf20Sopenharmony_ci u8 id = 0; 12388c2ecf20Sopenharmony_ci char *p = ""; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci /* Check if the adapter supports the needed features */ 12418c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 12428c2ecf20Sopenharmony_ci return -EIO; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); 12458c2ecf20Sopenharmony_ci if (decoder == NULL) 12468c2ecf20Sopenharmony_ci return -ENOMEM; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci sd = &decoder->sd; 12498c2ecf20Sopenharmony_ci v4l2_i2c_subdev_init(sd, client, &saa717x_ops); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci if (saa717x_write(sd, 0x5a4, 0xfe) && 12528c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5a5, 0x0f) && 12538c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5a6, 0x00) && 12548c2ecf20Sopenharmony_ci saa717x_write(sd, 0x5a7, 0x01)) 12558c2ecf20Sopenharmony_ci id = saa717x_read(sd, 0x5a0); 12568c2ecf20Sopenharmony_ci if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) { 12578c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id); 12588c2ecf20Sopenharmony_ci return -ENODEV; 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_ci if (id == 0xc2) 12618c2ecf20Sopenharmony_ci p = "saa7173"; 12628c2ecf20Sopenharmony_ci else if (id == 0x32) 12638c2ecf20Sopenharmony_ci p = "saa7174A"; 12648c2ecf20Sopenharmony_ci else if (id == 0x6c) 12658c2ecf20Sopenharmony_ci p = "saa7174HL"; 12668c2ecf20Sopenharmony_ci else 12678c2ecf20Sopenharmony_ci p = "saa7171"; 12688c2ecf20Sopenharmony_ci v4l2_info(sd, "%s found @ 0x%x (%s)\n", p, 12698c2ecf20Sopenharmony_ci client->addr << 1, client->adapter->name); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci hdl = &decoder->hdl; 12728c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 9); 12738c2ecf20Sopenharmony_ci /* add in ascending ID order */ 12748c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12758c2ecf20Sopenharmony_ci V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); 12768c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12778c2ecf20Sopenharmony_ci V4L2_CID_CONTRAST, 0, 255, 1, 68); 12788c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12798c2ecf20Sopenharmony_ci V4L2_CID_SATURATION, 0, 255, 1, 64); 12808c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12818c2ecf20Sopenharmony_ci V4L2_CID_HUE, -128, 127, 1, 0); 12828c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12838c2ecf20Sopenharmony_ci V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000); 12848c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12858c2ecf20Sopenharmony_ci V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768); 12868c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12878c2ecf20Sopenharmony_ci V4L2_CID_AUDIO_BASS, -16, 15, 1, 0); 12888c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12898c2ecf20Sopenharmony_ci V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0); 12908c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops, 12918c2ecf20Sopenharmony_ci V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); 12928c2ecf20Sopenharmony_ci sd->ctrl_handler = hdl; 12938c2ecf20Sopenharmony_ci if (hdl->error) { 12948c2ecf20Sopenharmony_ci int err = hdl->error; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(hdl); 12978c2ecf20Sopenharmony_ci return err; 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci decoder->std = V4L2_STD_NTSC; 13018c2ecf20Sopenharmony_ci decoder->input = -1; 13028c2ecf20Sopenharmony_ci decoder->enable = 1; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci /* FIXME!! */ 13058c2ecf20Sopenharmony_ci decoder->playback = 0; /* initially capture mode used */ 13068c2ecf20Sopenharmony_ci decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */ 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci decoder->audio_input = 2; /* FIXME!! */ 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci decoder->tuner_audio_mode = TUNER_AUDIO_STEREO; 13118c2ecf20Sopenharmony_ci /* set volume, bass and treble */ 13128c2ecf20Sopenharmony_ci decoder->audio_main_vol_l = 6; 13138c2ecf20Sopenharmony_ci decoder->audio_main_vol_r = 6; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci v4l2_dbg(1, debug, sd, "writing init values\n"); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci /* FIXME!! */ 13188c2ecf20Sopenharmony_ci saa717x_write_regs(sd, reg_init_initialize); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci v4l2_ctrl_handler_setup(hdl); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 13238c2ecf20Sopenharmony_ci schedule_timeout(2*HZ); 13248c2ecf20Sopenharmony_ci return 0; 13258c2ecf20Sopenharmony_ci} 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_cistatic int saa717x_remove(struct i2c_client *client) 13288c2ecf20Sopenharmony_ci{ 13298c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = i2c_get_clientdata(client); 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci v4l2_device_unregister_subdev(sd); 13328c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(sd->ctrl_handler); 13338c2ecf20Sopenharmony_ci return 0; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------- */ 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_cistatic const struct i2c_device_id saa717x_id[] = { 13398c2ecf20Sopenharmony_ci { "saa717x", 0 }, 13408c2ecf20Sopenharmony_ci { } 13418c2ecf20Sopenharmony_ci}; 13428c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, saa717x_id); 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_cistatic struct i2c_driver saa717x_driver = { 13458c2ecf20Sopenharmony_ci .driver = { 13468c2ecf20Sopenharmony_ci .name = "saa717x", 13478c2ecf20Sopenharmony_ci }, 13488c2ecf20Sopenharmony_ci .probe = saa717x_probe, 13498c2ecf20Sopenharmony_ci .remove = saa717x_remove, 13508c2ecf20Sopenharmony_ci .id_table = saa717x_id, 13518c2ecf20Sopenharmony_ci}; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_cimodule_i2c_driver(saa717x_driver); 1354