16052ba35SHans Verkuil /* 26052ba35SHans Verkuil saa6752hs - i2c-driver for the saa6752hs by Philips 36052ba35SHans Verkuil 46052ba35SHans Verkuil Copyright (C) 2004 Andrew de Quincey 56052ba35SHans Verkuil 66052ba35SHans Verkuil AC-3 support: 76052ba35SHans Verkuil 86052ba35SHans Verkuil Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> 96052ba35SHans Verkuil 106052ba35SHans Verkuil This program is free software; you can redistribute it and/or modify 116052ba35SHans Verkuil it under the terms of the GNU General Public License vs published by 126052ba35SHans Verkuil the Free Software Foundation; either version 2 of the License, or 136052ba35SHans Verkuil (at your option) any later version. 146052ba35SHans Verkuil 156052ba35SHans Verkuil This program is distributed in the hope that it will be useful, 166052ba35SHans Verkuil but WITHOUT ANY WARRANTY; without even the implied warranty of 176052ba35SHans Verkuil MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 186052ba35SHans Verkuil GNU General Public License for more details. 196052ba35SHans Verkuil 206052ba35SHans Verkuil You should have received a copy of the GNU General Public License 216052ba35SHans Verkuil along with this program; if not, write to the Free Software 226052ba35SHans Verkuil Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. 236052ba35SHans Verkuil */ 246052ba35SHans Verkuil 256052ba35SHans Verkuil #include <linux/module.h> 266052ba35SHans Verkuil #include <linux/kernel.h> 276052ba35SHans Verkuil #include <linux/string.h> 286052ba35SHans Verkuil #include <linux/timer.h> 296052ba35SHans Verkuil #include <linux/delay.h> 306052ba35SHans Verkuil #include <linux/errno.h> 316052ba35SHans Verkuil #include <linux/slab.h> 326052ba35SHans Verkuil #include <linux/poll.h> 336052ba35SHans Verkuil #include <linux/i2c.h> 346052ba35SHans Verkuil #include <linux/types.h> 356052ba35SHans Verkuil #include <linux/videodev2.h> 366052ba35SHans Verkuil #include <linux/init.h> 376052ba35SHans Verkuil #include <linux/crc32.h> 386052ba35SHans Verkuil #include <media/v4l2-device.h> 396052ba35SHans Verkuil #include <media/v4l2-ctrls.h> 406052ba35SHans Verkuil #include <media/v4l2-common.h> 416052ba35SHans Verkuil 426052ba35SHans Verkuil #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 436052ba35SHans Verkuil #define MPEG_VIDEO_MAX_BITRATE_MAX 27000 446052ba35SHans Verkuil #define MPEG_TOTAL_TARGET_BITRATE_MAX 27000 456052ba35SHans Verkuil #define MPEG_PID_MAX ((1 << 14) - 1) 466052ba35SHans Verkuil 476052ba35SHans Verkuil 486052ba35SHans Verkuil MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); 496052ba35SHans Verkuil MODULE_AUTHOR("Andrew de Quincey"); 506052ba35SHans Verkuil MODULE_LICENSE("GPL"); 516052ba35SHans Verkuil 526052ba35SHans Verkuil enum saa6752hs_videoformat { 536052ba35SHans Verkuil SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ 546052ba35SHans Verkuil SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ 556052ba35SHans Verkuil SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */ 566052ba35SHans Verkuil SAA6752HS_VF_SIF = 3, /* SIF video format: 352x288 */ 576052ba35SHans Verkuil SAA6752HS_VF_UNKNOWN, 586052ba35SHans Verkuil }; 596052ba35SHans Verkuil 606052ba35SHans Verkuil struct saa6752hs_mpeg_params { 616052ba35SHans Verkuil /* transport streams */ 626052ba35SHans Verkuil __u16 ts_pid_pmt; 636052ba35SHans Verkuil __u16 ts_pid_audio; 646052ba35SHans Verkuil __u16 ts_pid_video; 656052ba35SHans Verkuil __u16 ts_pid_pcr; 666052ba35SHans Verkuil 676052ba35SHans Verkuil /* audio */ 686052ba35SHans Verkuil enum v4l2_mpeg_audio_encoding au_encoding; 696052ba35SHans Verkuil enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; 706052ba35SHans Verkuil enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate; 716052ba35SHans Verkuil 726052ba35SHans Verkuil /* video */ 736052ba35SHans Verkuil enum v4l2_mpeg_video_aspect vi_aspect; 746052ba35SHans Verkuil enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode; 756052ba35SHans Verkuil __u32 vi_bitrate; 766052ba35SHans Verkuil __u32 vi_bitrate_peak; 776052ba35SHans Verkuil }; 786052ba35SHans Verkuil 796052ba35SHans Verkuil static const struct v4l2_format v4l2_format_table[] = 806052ba35SHans Verkuil { 816052ba35SHans Verkuil [SAA6752HS_VF_D1] = 826052ba35SHans Verkuil { .fmt = { .pix = { .width = 720, .height = 576 }}}, 836052ba35SHans Verkuil [SAA6752HS_VF_2_3_D1] = 846052ba35SHans Verkuil { .fmt = { .pix = { .width = 480, .height = 576 }}}, 856052ba35SHans Verkuil [SAA6752HS_VF_1_2_D1] = 866052ba35SHans Verkuil { .fmt = { .pix = { .width = 352, .height = 576 }}}, 876052ba35SHans Verkuil [SAA6752HS_VF_SIF] = 886052ba35SHans Verkuil { .fmt = { .pix = { .width = 352, .height = 288 }}}, 896052ba35SHans Verkuil [SAA6752HS_VF_UNKNOWN] = 906052ba35SHans Verkuil { .fmt = { .pix = { .width = 0, .height = 0}}}, 916052ba35SHans Verkuil }; 926052ba35SHans Verkuil 936052ba35SHans Verkuil struct saa6752hs_state { 946052ba35SHans Verkuil struct v4l2_subdev sd; 956052ba35SHans Verkuil struct v4l2_ctrl_handler hdl; 966052ba35SHans Verkuil struct { /* video bitrate mode control cluster */ 976052ba35SHans Verkuil struct v4l2_ctrl *video_bitrate_mode; 986052ba35SHans Verkuil struct v4l2_ctrl *video_bitrate; 996052ba35SHans Verkuil struct v4l2_ctrl *video_bitrate_peak; 1006052ba35SHans Verkuil }; 1016052ba35SHans Verkuil u32 revision; 1026052ba35SHans Verkuil int has_ac3; 1036052ba35SHans Verkuil struct saa6752hs_mpeg_params params; 1046052ba35SHans Verkuil enum saa6752hs_videoformat video_format; 1056052ba35SHans Verkuil v4l2_std_id standard; 1066052ba35SHans Verkuil }; 1076052ba35SHans Verkuil 1086052ba35SHans Verkuil enum saa6752hs_command { 1096052ba35SHans Verkuil SAA6752HS_COMMAND_RESET = 0, 1106052ba35SHans Verkuil SAA6752HS_COMMAND_STOP = 1, 1116052ba35SHans Verkuil SAA6752HS_COMMAND_START = 2, 1126052ba35SHans Verkuil SAA6752HS_COMMAND_PAUSE = 3, 1136052ba35SHans Verkuil SAA6752HS_COMMAND_RECONFIGURE = 4, 1146052ba35SHans Verkuil SAA6752HS_COMMAND_SLEEP = 5, 1156052ba35SHans Verkuil SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6, 1166052ba35SHans Verkuil 1176052ba35SHans Verkuil SAA6752HS_COMMAND_MAX 1186052ba35SHans Verkuil }; 1196052ba35SHans Verkuil 1206052ba35SHans Verkuil static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd) 1216052ba35SHans Verkuil { 1226052ba35SHans Verkuil return container_of(sd, struct saa6752hs_state, sd); 1236052ba35SHans Verkuil } 1246052ba35SHans Verkuil 1256052ba35SHans Verkuil /* ---------------------------------------------------------------------- */ 1266052ba35SHans Verkuil 1276052ba35SHans Verkuil static const u8 PAT[] = { 1286052ba35SHans Verkuil 0xc2, /* i2c register */ 1296052ba35SHans Verkuil 0x00, /* table number for encoder */ 1306052ba35SHans Verkuil 1316052ba35SHans Verkuil 0x47, /* sync */ 1326052ba35SHans Verkuil 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */ 1336052ba35SHans Verkuil 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ 1346052ba35SHans Verkuil 1356052ba35SHans Verkuil 0x00, /* PSI pointer to start of table */ 1366052ba35SHans Verkuil 1376052ba35SHans Verkuil 0x00, /* tid(0) */ 1386052ba35SHans Verkuil 0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */ 1396052ba35SHans Verkuil 1406052ba35SHans Verkuil 0x00, 0x01, /* transport_stream_id(1) */ 1416052ba35SHans Verkuil 1426052ba35SHans Verkuil 0xc1, /* version_number(0), current_next_indicator(1) */ 1436052ba35SHans Verkuil 1446052ba35SHans Verkuil 0x00, 0x00, /* section_number(0), last_section_number(0) */ 1456052ba35SHans Verkuil 1466052ba35SHans Verkuil 0x00, 0x01, /* program_number(1) */ 1476052ba35SHans Verkuil 1486052ba35SHans Verkuil 0xe0, 0x00, /* PMT PID */ 1496052ba35SHans Verkuil 1506052ba35SHans Verkuil 0x00, 0x00, 0x00, 0x00 /* CRC32 */ 1516052ba35SHans Verkuil }; 1526052ba35SHans Verkuil 1536052ba35SHans Verkuil static const u8 PMT[] = { 1546052ba35SHans Verkuil 0xc2, /* i2c register */ 1556052ba35SHans Verkuil 0x01, /* table number for encoder */ 1566052ba35SHans Verkuil 1576052ba35SHans Verkuil 0x47, /* sync */ 1586052ba35SHans Verkuil 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */ 1596052ba35SHans Verkuil 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ 1606052ba35SHans Verkuil 1616052ba35SHans Verkuil 0x00, /* PSI pointer to start of table */ 1626052ba35SHans Verkuil 1636052ba35SHans Verkuil 0x02, /* tid(2) */ 1646052ba35SHans Verkuil 0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */ 1656052ba35SHans Verkuil 1666052ba35SHans Verkuil 0x00, 0x01, /* program_number(1) */ 1676052ba35SHans Verkuil 1686052ba35SHans Verkuil 0xc1, /* version_number(0), current_next_indicator(1) */ 1696052ba35SHans Verkuil 1706052ba35SHans Verkuil 0x00, 0x00, /* section_number(0), last_section_number(0) */ 1716052ba35SHans Verkuil 1726052ba35SHans Verkuil 0xe0, 0x00, /* PCR_PID */ 1736052ba35SHans Verkuil 1746052ba35SHans Verkuil 0xf0, 0x00, /* program_info_length(0) */ 1756052ba35SHans Verkuil 1766052ba35SHans Verkuil 0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */ 1776052ba35SHans Verkuil 0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */ 1786052ba35SHans Verkuil 1796052ba35SHans Verkuil 0x00, 0x00, 0x00, 0x00 /* CRC32 */ 1806052ba35SHans Verkuil }; 1816052ba35SHans Verkuil 1826052ba35SHans Verkuil static const u8 PMT_AC3[] = { 1836052ba35SHans Verkuil 0xc2, /* i2c register */ 1846052ba35SHans Verkuil 0x01, /* table number for encoder(1) */ 1856052ba35SHans Verkuil 0x47, /* sync */ 1866052ba35SHans Verkuil 1876052ba35SHans Verkuil 0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */ 1886052ba35SHans Verkuil 0x10, /* PMT PID (0x0010) */ 1896052ba35SHans Verkuil 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ 1906052ba35SHans Verkuil 1916052ba35SHans Verkuil 0x00, /* PSI pointer to start of table */ 1926052ba35SHans Verkuil 1936052ba35SHans Verkuil 0x02, /* TID (2) */ 1946052ba35SHans Verkuil 0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */ 1956052ba35SHans Verkuil 1966052ba35SHans Verkuil 0x00, 0x01, /* program_number(1) */ 1976052ba35SHans Verkuil 1986052ba35SHans Verkuil 0xc1, /* version_number(0), current_next_indicator(1) */ 1996052ba35SHans Verkuil 2006052ba35SHans Verkuil 0x00, 0x00, /* section_number(0), last_section_number(0) */ 2016052ba35SHans Verkuil 2026052ba35SHans Verkuil 0xe1, 0x04, /* PCR_PID (0x0104) */ 2036052ba35SHans Verkuil 2046052ba35SHans Verkuil 0xf0, 0x00, /* program_info_length(0) */ 2056052ba35SHans Verkuil 2066052ba35SHans Verkuil 0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */ 2076052ba35SHans Verkuil 0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */ 2086052ba35SHans Verkuil 0x6a, /* AC3 */ 2096052ba35SHans Verkuil 0x01, /* Descriptor_length(1) */ 2106052ba35SHans Verkuil 0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */ 2116052ba35SHans Verkuil 2126052ba35SHans Verkuil 0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */ 2136052ba35SHans Verkuil }; 2146052ba35SHans Verkuil 2156052ba35SHans Verkuil static const struct saa6752hs_mpeg_params param_defaults = 2166052ba35SHans Verkuil { 2176052ba35SHans Verkuil .ts_pid_pmt = 16, 2186052ba35SHans Verkuil .ts_pid_video = 260, 2196052ba35SHans Verkuil .ts_pid_audio = 256, 2206052ba35SHans Verkuil .ts_pid_pcr = 259, 2216052ba35SHans Verkuil 2226052ba35SHans Verkuil .vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, 2236052ba35SHans Verkuil .vi_bitrate = 4000, 2246052ba35SHans Verkuil .vi_bitrate_peak = 6000, 2256052ba35SHans Verkuil .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, 2266052ba35SHans Verkuil 2276052ba35SHans Verkuil .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 2286052ba35SHans Verkuil .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, 2296052ba35SHans Verkuil .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_256K, 2306052ba35SHans Verkuil }; 2316052ba35SHans Verkuil 2326052ba35SHans Verkuil /* ---------------------------------------------------------------------- */ 2336052ba35SHans Verkuil 2346052ba35SHans Verkuil static int saa6752hs_chip_command(struct i2c_client *client, 2356052ba35SHans Verkuil enum saa6752hs_command command) 2366052ba35SHans Verkuil { 2376052ba35SHans Verkuil unsigned char buf[3]; 2386052ba35SHans Verkuil unsigned long timeout; 2396052ba35SHans Verkuil int status = 0; 2406052ba35SHans Verkuil 2416052ba35SHans Verkuil /* execute the command */ 2426052ba35SHans Verkuil switch(command) { 2436052ba35SHans Verkuil case SAA6752HS_COMMAND_RESET: 2446052ba35SHans Verkuil buf[0] = 0x00; 2456052ba35SHans Verkuil break; 2466052ba35SHans Verkuil 2476052ba35SHans Verkuil case SAA6752HS_COMMAND_STOP: 2486052ba35SHans Verkuil buf[0] = 0x03; 2496052ba35SHans Verkuil break; 2506052ba35SHans Verkuil 2516052ba35SHans Verkuil case SAA6752HS_COMMAND_START: 2526052ba35SHans Verkuil buf[0] = 0x02; 2536052ba35SHans Verkuil break; 2546052ba35SHans Verkuil 2556052ba35SHans Verkuil case SAA6752HS_COMMAND_PAUSE: 2566052ba35SHans Verkuil buf[0] = 0x04; 2576052ba35SHans Verkuil break; 2586052ba35SHans Verkuil 2596052ba35SHans Verkuil case SAA6752HS_COMMAND_RECONFIGURE: 2606052ba35SHans Verkuil buf[0] = 0x05; 2616052ba35SHans Verkuil break; 2626052ba35SHans Verkuil 2636052ba35SHans Verkuil case SAA6752HS_COMMAND_SLEEP: 2646052ba35SHans Verkuil buf[0] = 0x06; 2656052ba35SHans Verkuil break; 2666052ba35SHans Verkuil 2676052ba35SHans Verkuil case SAA6752HS_COMMAND_RECONFIGURE_FORCE: 2686052ba35SHans Verkuil buf[0] = 0x07; 2696052ba35SHans Verkuil break; 2706052ba35SHans Verkuil 2716052ba35SHans Verkuil default: 2726052ba35SHans Verkuil return -EINVAL; 2736052ba35SHans Verkuil } 2746052ba35SHans Verkuil 2756052ba35SHans Verkuil /* set it and wait for it to be so */ 2766052ba35SHans Verkuil i2c_master_send(client, buf, 1); 2776052ba35SHans Verkuil timeout = jiffies + HZ * 3; 2786052ba35SHans Verkuil for (;;) { 2796052ba35SHans Verkuil /* get the current status */ 2806052ba35SHans Verkuil buf[0] = 0x10; 2816052ba35SHans Verkuil i2c_master_send(client, buf, 1); 2826052ba35SHans Verkuil i2c_master_recv(client, buf, 1); 2836052ba35SHans Verkuil 2846052ba35SHans Verkuil if (!(buf[0] & 0x20)) 2856052ba35SHans Verkuil break; 2866052ba35SHans Verkuil if (time_after(jiffies,timeout)) { 2876052ba35SHans Verkuil status = -ETIMEDOUT; 2886052ba35SHans Verkuil break; 2896052ba35SHans Verkuil } 2906052ba35SHans Verkuil 2916052ba35SHans Verkuil msleep(10); 2926052ba35SHans Verkuil } 2936052ba35SHans Verkuil 2946052ba35SHans Verkuil /* delay a bit to let encoder settle */ 2956052ba35SHans Verkuil msleep(50); 2966052ba35SHans Verkuil 2976052ba35SHans Verkuil return status; 2986052ba35SHans Verkuil } 2996052ba35SHans Verkuil 3006052ba35SHans Verkuil 3016052ba35SHans Verkuil static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val) 3026052ba35SHans Verkuil { 3036052ba35SHans Verkuil u8 buf[2]; 3046052ba35SHans Verkuil 3056052ba35SHans Verkuil buf[0] = reg; 3066052ba35SHans Verkuil buf[1] = val; 3076052ba35SHans Verkuil i2c_master_send(client, buf, 2); 3086052ba35SHans Verkuil } 3096052ba35SHans Verkuil 3106052ba35SHans Verkuil static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val) 3116052ba35SHans Verkuil { 3126052ba35SHans Verkuil u8 buf[3]; 3136052ba35SHans Verkuil 3146052ba35SHans Verkuil buf[0] = reg; 3156052ba35SHans Verkuil buf[1] = val >> 8; 3166052ba35SHans Verkuil buf[2] = val & 0xff; 3176052ba35SHans Verkuil i2c_master_send(client, buf, 3); 3186052ba35SHans Verkuil } 3196052ba35SHans Verkuil 3206052ba35SHans Verkuil static int saa6752hs_set_bitrate(struct i2c_client *client, 3216052ba35SHans Verkuil struct saa6752hs_state *h) 3226052ba35SHans Verkuil { 3236052ba35SHans Verkuil struct saa6752hs_mpeg_params *params = &h->params; 3246052ba35SHans Verkuil int tot_bitrate; 3256052ba35SHans Verkuil int is_384k; 3266052ba35SHans Verkuil 3276052ba35SHans Verkuil /* set the bitrate mode */ 3286052ba35SHans Verkuil set_reg8(client, 0x71, 3296052ba35SHans Verkuil params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 3306052ba35SHans Verkuil 3316052ba35SHans Verkuil /* set the video bitrate */ 3326052ba35SHans Verkuil if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { 3336052ba35SHans Verkuil /* set the target bitrate */ 3346052ba35SHans Verkuil set_reg16(client, 0x80, params->vi_bitrate); 3356052ba35SHans Verkuil 3366052ba35SHans Verkuil /* set the max bitrate */ 3376052ba35SHans Verkuil set_reg16(client, 0x81, params->vi_bitrate_peak); 3386052ba35SHans Verkuil tot_bitrate = params->vi_bitrate_peak; 3396052ba35SHans Verkuil } else { 3406052ba35SHans Verkuil /* set the target bitrate (no max bitrate for CBR) */ 3416052ba35SHans Verkuil set_reg16(client, 0x81, params->vi_bitrate); 3426052ba35SHans Verkuil tot_bitrate = params->vi_bitrate; 3436052ba35SHans Verkuil } 3446052ba35SHans Verkuil 3456052ba35SHans Verkuil /* set the audio encoding */ 3466052ba35SHans Verkuil set_reg8(client, 0x93, 3476052ba35SHans Verkuil params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); 3486052ba35SHans Verkuil 3496052ba35SHans Verkuil /* set the audio bitrate */ 3506052ba35SHans Verkuil if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) 3516052ba35SHans Verkuil is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; 3526052ba35SHans Verkuil else 3536052ba35SHans Verkuil is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; 3546052ba35SHans Verkuil set_reg8(client, 0x94, is_384k); 3556052ba35SHans Verkuil tot_bitrate += is_384k ? 384 : 256; 3566052ba35SHans Verkuil 3576052ba35SHans Verkuil /* Note: the total max bitrate is determined by adding the video and audio 3586052ba35SHans Verkuil bitrates together and also adding an extra 768kbit/s to stay on the 3596052ba35SHans Verkuil safe side. If more control should be required, then an extra MPEG control 3606052ba35SHans Verkuil should be added. */ 3616052ba35SHans Verkuil tot_bitrate += 768; 3626052ba35SHans Verkuil if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX) 3636052ba35SHans Verkuil tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; 3646052ba35SHans Verkuil 3656052ba35SHans Verkuil /* set the total bitrate */ 3666052ba35SHans Verkuil set_reg16(client, 0xb1, tot_bitrate); 3676052ba35SHans Verkuil return 0; 3686052ba35SHans Verkuil } 3696052ba35SHans Verkuil 3706052ba35SHans Verkuil static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl) 3716052ba35SHans Verkuil { 3726052ba35SHans Verkuil struct saa6752hs_state *h = 3736052ba35SHans Verkuil container_of(ctrl->handler, struct saa6752hs_state, hdl); 3746052ba35SHans Verkuil 3756052ba35SHans Verkuil switch (ctrl->id) { 3766052ba35SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 3776052ba35SHans Verkuil /* peak bitrate shall be >= normal bitrate */ 3786052ba35SHans Verkuil if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && 3796052ba35SHans Verkuil h->video_bitrate_peak->val < h->video_bitrate->val) 3806052ba35SHans Verkuil h->video_bitrate_peak->val = h->video_bitrate->val; 3816052ba35SHans Verkuil break; 3826052ba35SHans Verkuil } 3836052ba35SHans Verkuil return 0; 3846052ba35SHans Verkuil } 3856052ba35SHans Verkuil 3866052ba35SHans Verkuil static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl) 3876052ba35SHans Verkuil { 3886052ba35SHans Verkuil struct saa6752hs_state *h = 3896052ba35SHans Verkuil container_of(ctrl->handler, struct saa6752hs_state, hdl); 3906052ba35SHans Verkuil struct saa6752hs_mpeg_params *params = &h->params; 3916052ba35SHans Verkuil 3926052ba35SHans Verkuil switch (ctrl->id) { 3936052ba35SHans Verkuil case V4L2_CID_MPEG_STREAM_TYPE: 3946052ba35SHans Verkuil break; 3956052ba35SHans Verkuil case V4L2_CID_MPEG_STREAM_PID_PMT: 3966052ba35SHans Verkuil params->ts_pid_pmt = ctrl->val; 3976052ba35SHans Verkuil break; 3986052ba35SHans Verkuil case V4L2_CID_MPEG_STREAM_PID_AUDIO: 3996052ba35SHans Verkuil params->ts_pid_audio = ctrl->val; 4006052ba35SHans Verkuil break; 4016052ba35SHans Verkuil case V4L2_CID_MPEG_STREAM_PID_VIDEO: 4026052ba35SHans Verkuil params->ts_pid_video = ctrl->val; 4036052ba35SHans Verkuil break; 4046052ba35SHans Verkuil case V4L2_CID_MPEG_STREAM_PID_PCR: 4056052ba35SHans Verkuil params->ts_pid_pcr = ctrl->val; 4066052ba35SHans Verkuil break; 4076052ba35SHans Verkuil case V4L2_CID_MPEG_AUDIO_ENCODING: 4086052ba35SHans Verkuil params->au_encoding = ctrl->val; 4096052ba35SHans Verkuil break; 4106052ba35SHans Verkuil case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 4116052ba35SHans Verkuil params->au_l2_bitrate = ctrl->val; 4126052ba35SHans Verkuil break; 4136052ba35SHans Verkuil case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 4146052ba35SHans Verkuil params->au_ac3_bitrate = ctrl->val; 4156052ba35SHans Verkuil break; 4166052ba35SHans Verkuil case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 4176052ba35SHans Verkuil break; 4186052ba35SHans Verkuil case V4L2_CID_MPEG_VIDEO_ENCODING: 4196052ba35SHans Verkuil break; 4206052ba35SHans Verkuil case V4L2_CID_MPEG_VIDEO_ASPECT: 4216052ba35SHans Verkuil params->vi_aspect = ctrl->val; 4226052ba35SHans Verkuil break; 4236052ba35SHans Verkuil case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 4246052ba35SHans Verkuil params->vi_bitrate_mode = ctrl->val; 4256052ba35SHans Verkuil params->vi_bitrate = h->video_bitrate->val / 1000; 4266052ba35SHans Verkuil params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000; 4276052ba35SHans Verkuil v4l2_ctrl_activate(h->video_bitrate_peak, 4286052ba35SHans Verkuil ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 4296052ba35SHans Verkuil break; 4306052ba35SHans Verkuil default: 4316052ba35SHans Verkuil return -EINVAL; 4326052ba35SHans Verkuil } 4336052ba35SHans Verkuil return 0; 4346052ba35SHans Verkuil } 4356052ba35SHans Verkuil 4366052ba35SHans Verkuil static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) 4376052ba35SHans Verkuil { 4386052ba35SHans Verkuil unsigned char buf[9], buf2[4]; 4396052ba35SHans Verkuil struct saa6752hs_state *h = to_state(sd); 4406052ba35SHans Verkuil struct i2c_client *client = v4l2_get_subdevdata(sd); 4416052ba35SHans Verkuil unsigned size; 4426052ba35SHans Verkuil u32 crc; 4436052ba35SHans Verkuil unsigned char localPAT[256]; 4446052ba35SHans Verkuil unsigned char localPMT[256]; 4456052ba35SHans Verkuil 4466052ba35SHans Verkuil /* Set video format - must be done first as it resets other settings */ 4476052ba35SHans Verkuil set_reg8(client, 0x41, h->video_format); 4486052ba35SHans Verkuil 4496052ba35SHans Verkuil /* Set number of lines in input signal */ 4506052ba35SHans Verkuil set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0); 4516052ba35SHans Verkuil 4526052ba35SHans Verkuil /* set bitrate */ 4536052ba35SHans Verkuil saa6752hs_set_bitrate(client, h); 4546052ba35SHans Verkuil 4556052ba35SHans Verkuil /* Set GOP structure {3, 13} */ 4566052ba35SHans Verkuil set_reg16(client, 0x72, 0x030d); 4576052ba35SHans Verkuil 4586052ba35SHans Verkuil /* Set minimum Q-scale {4} */ 4596052ba35SHans Verkuil set_reg8(client, 0x82, 0x04); 4606052ba35SHans Verkuil 4616052ba35SHans Verkuil /* Set maximum Q-scale {12} */ 4626052ba35SHans Verkuil set_reg8(client, 0x83, 0x0c); 4636052ba35SHans Verkuil 4646052ba35SHans Verkuil /* Set Output Protocol */ 4656052ba35SHans Verkuil set_reg8(client, 0xd0, 0x81); 4666052ba35SHans Verkuil 4676052ba35SHans Verkuil /* Set video output stream format {TS} */ 4686052ba35SHans Verkuil set_reg8(client, 0xb0, 0x05); 4696052ba35SHans Verkuil 4706052ba35SHans Verkuil /* Set leading null byte for TS */ 4716052ba35SHans Verkuil set_reg16(client, 0xf6, leading_null_bytes); 4726052ba35SHans Verkuil 4736052ba35SHans Verkuil /* compute PAT */ 4746052ba35SHans Verkuil memcpy(localPAT, PAT, sizeof(PAT)); 4756052ba35SHans Verkuil localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f); 4766052ba35SHans Verkuil localPAT[18] = h->params.ts_pid_pmt & 0xff; 4776052ba35SHans Verkuil crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4); 4786052ba35SHans Verkuil localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF; 4796052ba35SHans Verkuil localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF; 4806052ba35SHans Verkuil localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF; 4816052ba35SHans Verkuil localPAT[sizeof(PAT) - 1] = crc & 0xFF; 4826052ba35SHans Verkuil 4836052ba35SHans Verkuil /* compute PMT */ 4846052ba35SHans Verkuil if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { 4856052ba35SHans Verkuil size = sizeof(PMT_AC3); 4866052ba35SHans Verkuil memcpy(localPMT, PMT_AC3, size); 4876052ba35SHans Verkuil } else { 4886052ba35SHans Verkuil size = sizeof(PMT); 4896052ba35SHans Verkuil memcpy(localPMT, PMT, size); 4906052ba35SHans Verkuil } 4916052ba35SHans Verkuil localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); 4926052ba35SHans Verkuil localPMT[4] = h->params.ts_pid_pmt & 0xff; 4936052ba35SHans Verkuil localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); 4946052ba35SHans Verkuil localPMT[16] = h->params.ts_pid_pcr & 0xFF; 4956052ba35SHans Verkuil localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F); 4966052ba35SHans Verkuil localPMT[21] = h->params.ts_pid_video & 0xFF; 4976052ba35SHans Verkuil localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); 4986052ba35SHans Verkuil localPMT[26] = h->params.ts_pid_audio & 0xFF; 4996052ba35SHans Verkuil crc = crc32_be(~0, &localPMT[7], size - 7 - 4); 5006052ba35SHans Verkuil localPMT[size - 4] = (crc >> 24) & 0xFF; 5016052ba35SHans Verkuil localPMT[size - 3] = (crc >> 16) & 0xFF; 5026052ba35SHans Verkuil localPMT[size - 2] = (crc >> 8) & 0xFF; 5036052ba35SHans Verkuil localPMT[size - 1] = crc & 0xFF; 5046052ba35SHans Verkuil 5056052ba35SHans Verkuil /* Set Audio PID */ 5066052ba35SHans Verkuil set_reg16(client, 0xc1, h->params.ts_pid_audio); 5076052ba35SHans Verkuil 5086052ba35SHans Verkuil /* Set Video PID */ 5096052ba35SHans Verkuil set_reg16(client, 0xc0, h->params.ts_pid_video); 5106052ba35SHans Verkuil 5116052ba35SHans Verkuil /* Set PCR PID */ 5126052ba35SHans Verkuil set_reg16(client, 0xc4, h->params.ts_pid_pcr); 5136052ba35SHans Verkuil 5146052ba35SHans Verkuil /* Send SI tables */ 5156052ba35SHans Verkuil i2c_master_send(client, localPAT, sizeof(PAT)); 5166052ba35SHans Verkuil i2c_master_send(client, localPMT, size); 5176052ba35SHans Verkuil 5186052ba35SHans Verkuil /* mute then unmute audio. This removes buzzing artefacts */ 5196052ba35SHans Verkuil set_reg8(client, 0xa4, 1); 5206052ba35SHans Verkuil set_reg8(client, 0xa4, 0); 5216052ba35SHans Verkuil 5226052ba35SHans Verkuil /* start it going */ 5236052ba35SHans Verkuil saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); 5246052ba35SHans Verkuil 5256052ba35SHans Verkuil /* readout current state */ 5266052ba35SHans Verkuil buf[0] = 0xE1; 5276052ba35SHans Verkuil buf[1] = 0xA7; 5286052ba35SHans Verkuil buf[2] = 0xFE; 5296052ba35SHans Verkuil buf[3] = 0x82; 5306052ba35SHans Verkuil buf[4] = 0xB0; 5316052ba35SHans Verkuil i2c_master_send(client, buf, 5); 5326052ba35SHans Verkuil i2c_master_recv(client, buf2, 4); 5336052ba35SHans Verkuil 5346052ba35SHans Verkuil /* change aspect ratio */ 5356052ba35SHans Verkuil buf[0] = 0xE0; 5366052ba35SHans Verkuil buf[1] = 0xA7; 5376052ba35SHans Verkuil buf[2] = 0xFE; 5386052ba35SHans Verkuil buf[3] = 0x82; 5396052ba35SHans Verkuil buf[4] = 0xB0; 5406052ba35SHans Verkuil buf[5] = buf2[0]; 5416052ba35SHans Verkuil switch (h->params.vi_aspect) { 5426052ba35SHans Verkuil case V4L2_MPEG_VIDEO_ASPECT_16x9: 5436052ba35SHans Verkuil buf[6] = buf2[1] | 0x40; 5446052ba35SHans Verkuil break; 5456052ba35SHans Verkuil case V4L2_MPEG_VIDEO_ASPECT_4x3: 5466052ba35SHans Verkuil default: 5476052ba35SHans Verkuil buf[6] = buf2[1] & 0xBF; 5486052ba35SHans Verkuil break; 5496052ba35SHans Verkuil } 5506052ba35SHans Verkuil buf[7] = buf2[2]; 5516052ba35SHans Verkuil buf[8] = buf2[3]; 5526052ba35SHans Verkuil i2c_master_send(client, buf, 9); 5536052ba35SHans Verkuil 5546052ba35SHans Verkuil return 0; 5556052ba35SHans Verkuil } 5566052ba35SHans Verkuil 5576052ba35SHans Verkuil static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) 5586052ba35SHans Verkuil { 5596052ba35SHans Verkuil struct saa6752hs_state *h = to_state(sd); 5606052ba35SHans Verkuil 5616052ba35SHans Verkuil if (h->video_format == SAA6752HS_VF_UNKNOWN) 5626052ba35SHans Verkuil h->video_format = SAA6752HS_VF_D1; 5636052ba35SHans Verkuil f->width = v4l2_format_table[h->video_format].fmt.pix.width; 5646052ba35SHans Verkuil f->height = v4l2_format_table[h->video_format].fmt.pix.height; 5656052ba35SHans Verkuil f->code = V4L2_MBUS_FMT_FIXED; 5666052ba35SHans Verkuil f->field = V4L2_FIELD_INTERLACED; 5676052ba35SHans Verkuil f->colorspace = V4L2_COLORSPACE_SMPTE170M; 5686052ba35SHans Verkuil return 0; 5696052ba35SHans Verkuil } 5706052ba35SHans Verkuil 5716052ba35SHans Verkuil static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) 5726052ba35SHans Verkuil { 5736052ba35SHans Verkuil int dist_352, dist_480, dist_720; 5746052ba35SHans Verkuil 5756052ba35SHans Verkuil f->code = V4L2_MBUS_FMT_FIXED; 5766052ba35SHans Verkuil 5776052ba35SHans Verkuil dist_352 = abs(f->width - 352); 5786052ba35SHans Verkuil dist_480 = abs(f->width - 480); 5796052ba35SHans Verkuil dist_720 = abs(f->width - 720); 5806052ba35SHans Verkuil if (dist_720 < dist_480) { 5816052ba35SHans Verkuil f->width = 720; 5826052ba35SHans Verkuil f->height = 576; 5836052ba35SHans Verkuil } else if (dist_480 < dist_352) { 5846052ba35SHans Verkuil f->width = 480; 5856052ba35SHans Verkuil f->height = 576; 5866052ba35SHans Verkuil } else { 5876052ba35SHans Verkuil f->width = 352; 5886052ba35SHans Verkuil if (abs(f->height - 576) < abs(f->height - 288)) 5896052ba35SHans Verkuil f->height = 576; 5906052ba35SHans Verkuil else 5916052ba35SHans Verkuil f->height = 288; 5926052ba35SHans Verkuil } 5936052ba35SHans Verkuil f->field = V4L2_FIELD_INTERLACED; 5946052ba35SHans Verkuil f->colorspace = V4L2_COLORSPACE_SMPTE170M; 5956052ba35SHans Verkuil return 0; 5966052ba35SHans Verkuil } 5976052ba35SHans Verkuil 5986052ba35SHans Verkuil static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) 5996052ba35SHans Verkuil { 6006052ba35SHans Verkuil struct saa6752hs_state *h = to_state(sd); 6016052ba35SHans Verkuil 6026052ba35SHans Verkuil if (f->code != V4L2_MBUS_FMT_FIXED) 6036052ba35SHans Verkuil return -EINVAL; 6046052ba35SHans Verkuil 6056052ba35SHans Verkuil /* 6066052ba35SHans Verkuil FIXME: translate and round width/height into EMPRESS 6076052ba35SHans Verkuil subsample type: 6086052ba35SHans Verkuil 6096052ba35SHans Verkuil type | PAL | NTSC 6106052ba35SHans Verkuil --------------------------- 6116052ba35SHans Verkuil SIF | 352x288 | 352x240 6126052ba35SHans Verkuil 1/2 D1 | 352x576 | 352x480 6136052ba35SHans Verkuil 2/3 D1 | 480x576 | 480x480 6146052ba35SHans Verkuil D1 | 720x576 | 720x480 6156052ba35SHans Verkuil */ 6166052ba35SHans Verkuil 6176052ba35SHans Verkuil saa6752hs_try_mbus_fmt(sd, f); 6186052ba35SHans Verkuil if (f->width == 720) 6196052ba35SHans Verkuil h->video_format = SAA6752HS_VF_D1; 6206052ba35SHans Verkuil else if (f->width == 480) 6216052ba35SHans Verkuil h->video_format = SAA6752HS_VF_2_3_D1; 6226052ba35SHans Verkuil else if (f->height == 576) 6236052ba35SHans Verkuil h->video_format = SAA6752HS_VF_1_2_D1; 6246052ba35SHans Verkuil else 6256052ba35SHans Verkuil h->video_format = SAA6752HS_VF_SIF; 6266052ba35SHans Verkuil return 0; 6276052ba35SHans Verkuil } 6286052ba35SHans Verkuil 6296052ba35SHans Verkuil static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 6306052ba35SHans Verkuil { 6316052ba35SHans Verkuil struct saa6752hs_state *h = to_state(sd); 6326052ba35SHans Verkuil 6336052ba35SHans Verkuil h->standard = std; 6346052ba35SHans Verkuil return 0; 6356052ba35SHans Verkuil } 6366052ba35SHans Verkuil 6376052ba35SHans Verkuil /* ----------------------------------------------------------------------- */ 6386052ba35SHans Verkuil 6396052ba35SHans Verkuil static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = { 6406052ba35SHans Verkuil .try_ctrl = saa6752hs_try_ctrl, 6416052ba35SHans Verkuil .s_ctrl = saa6752hs_s_ctrl, 6426052ba35SHans Verkuil }; 6436052ba35SHans Verkuil 6446052ba35SHans Verkuil static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { 6456052ba35SHans Verkuil .init = saa6752hs_init, 6466052ba35SHans Verkuil }; 6476052ba35SHans Verkuil 6486052ba35SHans Verkuil static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { 649*8774bed9SLaurent Pinchart .s_std = saa6752hs_s_std, 6506052ba35SHans Verkuil .s_mbus_fmt = saa6752hs_s_mbus_fmt, 6516052ba35SHans Verkuil .try_mbus_fmt = saa6752hs_try_mbus_fmt, 6526052ba35SHans Verkuil .g_mbus_fmt = saa6752hs_g_mbus_fmt, 6536052ba35SHans Verkuil }; 6546052ba35SHans Verkuil 6556052ba35SHans Verkuil static const struct v4l2_subdev_ops saa6752hs_ops = { 6566052ba35SHans Verkuil .core = &saa6752hs_core_ops, 6576052ba35SHans Verkuil .video = &saa6752hs_video_ops, 6586052ba35SHans Verkuil }; 6596052ba35SHans Verkuil 6606052ba35SHans Verkuil static int saa6752hs_probe(struct i2c_client *client, 6616052ba35SHans Verkuil const struct i2c_device_id *id) 6626052ba35SHans Verkuil { 6636052ba35SHans Verkuil struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); 6646052ba35SHans Verkuil struct v4l2_subdev *sd; 6656052ba35SHans Verkuil struct v4l2_ctrl_handler *hdl; 6666052ba35SHans Verkuil u8 addr = 0x13; 6676052ba35SHans Verkuil u8 data[12]; 6686052ba35SHans Verkuil 6696052ba35SHans Verkuil v4l_info(client, "chip found @ 0x%x (%s)\n", 6706052ba35SHans Verkuil client->addr << 1, client->adapter->name); 6716052ba35SHans Verkuil if (h == NULL) 6726052ba35SHans Verkuil return -ENOMEM; 6736052ba35SHans Verkuil sd = &h->sd; 6746052ba35SHans Verkuil v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops); 6756052ba35SHans Verkuil 6766052ba35SHans Verkuil i2c_master_send(client, &addr, 1); 6776052ba35SHans Verkuil i2c_master_recv(client, data, sizeof(data)); 6786052ba35SHans Verkuil h->revision = (data[8] << 8) | data[9]; 6796052ba35SHans Verkuil h->has_ac3 = 0; 6806052ba35SHans Verkuil if (h->revision == 0x0206) { 6816052ba35SHans Verkuil h->has_ac3 = 1; 6826052ba35SHans Verkuil v4l_info(client, "supports AC-3\n"); 6836052ba35SHans Verkuil } 6846052ba35SHans Verkuil h->params = param_defaults; 6856052ba35SHans Verkuil 6866052ba35SHans Verkuil hdl = &h->hdl; 6876052ba35SHans Verkuil v4l2_ctrl_handler_init(hdl, 14); 6886052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 6896052ba35SHans Verkuil V4L2_CID_MPEG_AUDIO_ENCODING, 6906052ba35SHans Verkuil h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : 6916052ba35SHans Verkuil V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 6926052ba35SHans Verkuil 0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); 6936052ba35SHans Verkuil 6946052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 6956052ba35SHans Verkuil V4L2_CID_MPEG_AUDIO_L2_BITRATE, 6966052ba35SHans Verkuil V4L2_MPEG_AUDIO_L2_BITRATE_384K, 6976052ba35SHans Verkuil ~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) | 6986052ba35SHans Verkuil (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)), 6996052ba35SHans Verkuil V4L2_MPEG_AUDIO_L2_BITRATE_256K); 7006052ba35SHans Verkuil 7016052ba35SHans Verkuil if (h->has_ac3) 7026052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 7036052ba35SHans Verkuil V4L2_CID_MPEG_AUDIO_AC3_BITRATE, 7046052ba35SHans Verkuil V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 7056052ba35SHans Verkuil ~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | 7066052ba35SHans Verkuil (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)), 7076052ba35SHans Verkuil V4L2_MPEG_AUDIO_AC3_BITRATE_256K); 7086052ba35SHans Verkuil 7096052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 7106052ba35SHans Verkuil V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, 7116052ba35SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 7126052ba35SHans Verkuil ~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000), 7136052ba35SHans Verkuil V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); 7146052ba35SHans Verkuil 7156052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 7166052ba35SHans Verkuil V4L2_CID_MPEG_VIDEO_ENCODING, 7176052ba35SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 7186052ba35SHans Verkuil ~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2), 7196052ba35SHans Verkuil V4L2_MPEG_VIDEO_ENCODING_MPEG_2); 7206052ba35SHans Verkuil 7216052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 7226052ba35SHans Verkuil V4L2_CID_MPEG_VIDEO_ASPECT, 7236052ba35SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01, 7246052ba35SHans Verkuil V4L2_MPEG_VIDEO_ASPECT_4x3); 7256052ba35SHans Verkuil 7266052ba35SHans Verkuil h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, 7276052ba35SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, 7286052ba35SHans Verkuil 1000000, 27000000, 1000, 8000000); 7296052ba35SHans Verkuil 7306052ba35SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 7316052ba35SHans Verkuil V4L2_CID_MPEG_STREAM_TYPE, 7326052ba35SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 7336052ba35SHans Verkuil ~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS), 7346052ba35SHans Verkuil V4L2_MPEG_STREAM_TYPE_MPEG2_TS); 7356052ba35SHans Verkuil 7366052ba35SHans Verkuil h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, 7376052ba35SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE_MODE, 7386052ba35SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, 7396052ba35SHans Verkuil V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); 7406052ba35SHans Verkuil h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, 7416052ba35SHans Verkuil V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000); 7426052ba35SHans Verkuil v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, 7436052ba35SHans Verkuil V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16); 7446052ba35SHans Verkuil v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, 7456052ba35SHans Verkuil V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260); 7466052ba35SHans Verkuil v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, 7476052ba35SHans Verkuil V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256); 7486052ba35SHans Verkuil v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, 7496052ba35SHans Verkuil V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259); 7506052ba35SHans Verkuil sd->ctrl_handler = hdl; 7516052ba35SHans Verkuil if (hdl->error) { 7526052ba35SHans Verkuil int err = hdl->error; 7536052ba35SHans Verkuil 7546052ba35SHans Verkuil v4l2_ctrl_handler_free(hdl); 7556052ba35SHans Verkuil kfree(h); 7566052ba35SHans Verkuil return err; 7576052ba35SHans Verkuil } 7586052ba35SHans Verkuil v4l2_ctrl_cluster(3, &h->video_bitrate_mode); 7596052ba35SHans Verkuil v4l2_ctrl_handler_setup(hdl); 7606052ba35SHans Verkuil h->standard = 0; /* Assume 625 input lines */ 7616052ba35SHans Verkuil return 0; 7626052ba35SHans Verkuil } 7636052ba35SHans Verkuil 7646052ba35SHans Verkuil static int saa6752hs_remove(struct i2c_client *client) 7656052ba35SHans Verkuil { 7666052ba35SHans Verkuil struct v4l2_subdev *sd = i2c_get_clientdata(client); 7676052ba35SHans Verkuil 7686052ba35SHans Verkuil v4l2_device_unregister_subdev(sd); 7696052ba35SHans Verkuil v4l2_ctrl_handler_free(&to_state(sd)->hdl); 7706052ba35SHans Verkuil kfree(to_state(sd)); 7716052ba35SHans Verkuil return 0; 7726052ba35SHans Verkuil } 7736052ba35SHans Verkuil 7746052ba35SHans Verkuil static const struct i2c_device_id saa6752hs_id[] = { 7756052ba35SHans Verkuil { "saa6752hs", 0 }, 7766052ba35SHans Verkuil { } 7776052ba35SHans Verkuil }; 7786052ba35SHans Verkuil MODULE_DEVICE_TABLE(i2c, saa6752hs_id); 7796052ba35SHans Verkuil 7806052ba35SHans Verkuil static struct i2c_driver saa6752hs_driver = { 7816052ba35SHans Verkuil .driver = { 7826052ba35SHans Verkuil .owner = THIS_MODULE, 7836052ba35SHans Verkuil .name = "saa6752hs", 7846052ba35SHans Verkuil }, 7856052ba35SHans Verkuil .probe = saa6752hs_probe, 7866052ba35SHans Verkuil .remove = saa6752hs_remove, 7876052ba35SHans Verkuil .id_table = saa6752hs_id, 7886052ba35SHans Verkuil }; 7896052ba35SHans Verkuil 7906052ba35SHans Verkuil module_i2c_driver(saa6752hs_driver); 791