^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // saa711x - Philips SAA711x video decoder driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // This driver can work with saa7111, saa7111a, saa7113, saa7114,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // saa7115 and saa7118.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Based on saa7114 driver by Maxim Yevtyushkin, which is based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // the saa7111 driver by Dave Perks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // Copyright (C) 1998 Dave Perks <dperks@ibm.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // Slight changes for video timing and attachment output by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // Wolfgang Scherr <scherr@net4you.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) // Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) // by Ronald Bultje <rbultje@ronald.bitfreak.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) // Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) // (2/17/2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) // VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) // Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) // SAA7111, SAA7113 and SAA7118 support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "saa711x_regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <media/v4l2-mc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <media/i2c/saa7115.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define VRES_60HZ (480+16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) "Hans Verkuil, Mauro Carvalho Chehab");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static bool debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) module_param(debug, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MODULE_PARM_DESC(debug, "Debug level (0-1)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) enum saa711x_model {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) SAA7111A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) SAA7111,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) SAA7113,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) GM7113C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) SAA7114,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) SAA7115,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) SAA7118,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) enum saa711x_pads {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) SAA711X_PAD_IF_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) SAA711X_PAD_VID_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) SAA711X_NUM_PADS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct saa711x_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #ifdef CONFIG_MEDIA_CONTROLLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct media_pad pads[SAA711X_NUM_PADS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct v4l2_ctrl_handler hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* chroma gain control cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct v4l2_ctrl *agc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct v4l2_ctrl *gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) v4l2_std_id std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int radio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) enum saa711x_model ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 audclk_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 crystal_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bool ucgc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u8 cgcdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) bool apll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) bool double_asclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return container_of(sd, struct saa711x_state, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return i2c_smbus_write_byte_data(client, reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Sanity routine to check if a register is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int saa711x_has_reg(const int id, const u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (id == SAA7111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (id == SAA7111A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) reg != 0x14 && reg != 0x18 && reg != 0x19 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) reg != 0x1d && reg != 0x1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* common for saa7113/4/5/8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case GM7113C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case SAA7113:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) reg != 0x5d && reg < 0x63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case SAA7114:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) reg != 0x81 && reg < 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case SAA7115:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case SAA7118:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned char reg, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) while (*regs != 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) reg = *(regs++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) data = *(regs++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* According with datasheets, reserved regs should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) filled with 0 - seems better not to touch on they */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (saa711x_has_reg(state->ident, reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (saa711x_write(sd, reg, data) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return i2c_smbus_read_byte_data(client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* SAA7111 initialization table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static const unsigned char saa7111_init[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) R_01_INC_DELAY, 0x00, /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /*front end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * GAFIX=0, GAI1=256, GAI2=256 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* decoder */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * pixels after end of last line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * work with NTSC, too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * VTRC=1, HPLL=0, VNOI=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * VBLB=0, UPTCV=0, APER=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) R_0A_LUMA_BRIGHT_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) R_0C_CHROMA_SAT_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) R_0D_CHROMA_HUE_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * FCTC=0, CHBW=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) R_15_VGATE_START_FID_CHG, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) R_16_VGATE_STOP, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * This table has one illegal value, and some values that are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * correct according to the datasheet initialization table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * If you need a table with legal/default values tell the driver in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * i2c_board_info.platform_data, and you will get the gm7113c_init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * table instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* SAA7113 Init codes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static const unsigned char saa7113_init[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) R_01_INC_DELAY, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) R_02_INPUT_CNTL_1, 0xc2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) R_03_INPUT_CNTL_2, 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) R_04_INPUT_CNTL_3, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) R_05_INPUT_CNTL_4, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) R_06_H_SYNC_START, 0x89, /* Illegal value -119,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * min. value = -108 (0x94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) R_07_H_SYNC_STOP, 0x0d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) R_08_SYNC_CNTL, 0x88, /* Not datasheet default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * HTC = VTR mode, should be 0x98 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) R_09_LUMA_CNTL, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) R_0A_LUMA_BRIGHT_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) R_0B_LUMA_CONTRAST_CNTL, 0x47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) R_0C_CHROMA_SAT_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) R_0D_CHROMA_HUE_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) R_0E_CHROMA_CNTL_1, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) R_0F_CHROMA_GAIN_CNTL, 0x2a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * VRLN enabled, should be 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) R_11_MODE_DELAY_CNTL, 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * should be 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) R_13_RT_X_PORT_OUT_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) R_15_VGATE_START_FID_CHG, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) R_16_VGATE_STOP, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * GM7113C is a clone of the SAA7113 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * This init table is copied out of the saa7113 datasheet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * In R_08 we enable "Automatic Field Detection" [AUFD],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * this is disabled when saa711x_set_v4lstd is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static const unsigned char gm7113c_init[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) R_01_INC_DELAY, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) R_02_INPUT_CNTL_1, 0xc0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) R_03_INPUT_CNTL_2, 0x33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) R_04_INPUT_CNTL_3, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) R_05_INPUT_CNTL_4, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) R_06_H_SYNC_START, 0xe9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) R_07_H_SYNC_STOP, 0x0d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) R_08_SYNC_CNTL, 0x98,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) R_09_LUMA_CNTL, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) R_0A_LUMA_BRIGHT_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) R_0B_LUMA_CONTRAST_CNTL, 0x47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) R_0C_CHROMA_SAT_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) R_0D_CHROMA_HUE_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) R_0E_CHROMA_CNTL_1, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) R_0F_CHROMA_GAIN_CNTL, 0x2a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) R_10_CHROMA_CNTL_2, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) R_11_MODE_DELAY_CNTL, 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) R_12_RT_SIGNAL_CNTL, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) R_13_RT_X_PORT_OUT_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) R_15_VGATE_START_FID_CHG, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) R_16_VGATE_STOP, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* If a value differs from the Hauppauge driver values, then the comment starts with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) Hauppauge driver sets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* SAA7114 and SAA7115 initialization table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static const unsigned char saa7115_init_auto_input[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* Front-End Part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) R_01_INC_DELAY, 0x48, /* white peak control disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* Decoder Part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) R_0D_CHROMA_HUE_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) R_11_MODE_DELAY_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) R_19_RAW_DATA_OFF_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* Power Device Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Used to reset saa7113, saa7114 and saa7115 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static const unsigned char saa7115_cfg_reset_scaler[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* ============== SAA7715 VIDEO templates ============= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static const unsigned char saa7115_cfg_60hz_video[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) R_15_VGATE_START_FID_CHG, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) R_16_VGATE_STOP, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* Task A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) R_90_A_TASK_HANDLING_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* hoffset low (input), 0x0002 is minimum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* hsize low (input), 0x02d0 = 720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) R_98_A_VERT_INPUT_WINDOW_START, 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* Task B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) R_C0_B_TASK_HANDLING_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* 0x0002 is minimum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* 0x02d0 = 720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* vwindow start 0x12 = 18 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* vwindow length 0xf8 = 248 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* hwindow 0x02d0 = 720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) R_F5_PULSGEN_LINE_LENGTH, 0xad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static const unsigned char saa7115_cfg_50hz_video[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) R_80_GLOBAL_CNTL_1, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) R_16_VGATE_STOP, 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) R_0E_CHROMA_CNTL_1, 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* Task A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) R_90_A_TASK_HANDLING_CNTL, 0x81,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* This is weird: the datasheet says that you should use 2 as the minimum value, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* hoffset low (input), 0x0002 is minimum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* hsize low (input), 0x02d0 = 720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) R_98_A_VERT_INPUT_WINDOW_START, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* vsize 0x12 = 18 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* hsize 0x05a0 = 1440 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Task B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) R_C0_B_TASK_HANDLING_CNTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* This is weird: the datasheet says that you should use 2 as the minimum value, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* hoffset low (input), 0x0002 is minimum. See comment above. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* hsize 0x02d0 = 720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* voffset 0x16 = 22 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* vsize 0x0120 = 288 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* hsize 0x02d0 = 720 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) R_F5_PULSGEN_LINE_LENGTH, 0xb0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* ============== SAA7715 VIDEO templates (end) ======= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static const unsigned char saa7115_cfg_vbi_on[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static const unsigned char saa7115_cfg_vbi_off[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static const unsigned char saa7115_init_misc[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) R_84_I_PORT_SIGNAL_DEF, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) R_85_I_PORT_SIGNAL_POLAR, 0x21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* Task A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) R_A0_A_HORIZ_PRESCALING, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) R_A1_A_ACCUMULATION_LENGTH, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* Configure controls at nominal value*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* must be horiz lum scaling / 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* must be offset luma / 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* Task B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) R_D0_B_HORIZ_PRESCALING, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) R_D1_B_ACCUMULATION_LENGTH, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /* Configure controls at nominal value*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /* hor lum scaling 0x0400 = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* must be hor lum scaling / 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* must be offset luma / 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) R_F3_PLL_INCREMENT, 0x46,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) R_F4_PLL2_STATUS, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) R_F8_PULSE_B_POS, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) R_F9_PULSE_B_POS_MSB, 0x4b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) R_FA_PULSE_C_POS, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) R_FB_PULSE_C_POS_MSB, 0x4b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* PLL2 lock detection settings: 71 lines 50% phase error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* Turn off VBI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) R_41_LCR_BASE, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) R_41_LCR_BASE+1, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) R_41_LCR_BASE+2, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) R_41_LCR_BASE+3, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) R_41_LCR_BASE+4, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) R_41_LCR_BASE+5, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) R_41_LCR_BASE+6, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) R_41_LCR_BASE+7, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) R_41_LCR_BASE+8, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) R_41_LCR_BASE+9, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) R_41_LCR_BASE+10, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) R_41_LCR_BASE+11, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) R_41_LCR_BASE+12, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) R_41_LCR_BASE+13, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) R_41_LCR_BASE+14, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) R_41_LCR_BASE+15, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) R_41_LCR_BASE+16, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) R_41_LCR_BASE+17, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) R_41_LCR_BASE+18, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) R_41_LCR_BASE+19, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) R_41_LCR_BASE+20, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) R_41_LCR_BASE+21, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) R_41_LCR_BASE+22, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) R_58_PROGRAM_FRAMING_CODE, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) R_59_H_OFF_FOR_SLICER, 0x47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) R_5D_DID, 0xbd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) R_5E_SDID, 0x35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static int saa711x_odd_parity(u8 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) c ^= (c >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) c ^= (c >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) c ^= (c >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return c & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static int saa711x_decode_vps(u8 *dst, u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static const u8 biphase_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) u8 c, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) for (i = 0; i < 2 * 13; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dst[i / 2] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return err & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static int saa711x_decode_wss(u8 *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) static const int wss_bits[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 0, 0, 0, 1, 0, 1, 1, 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) unsigned char parity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int wss = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) int b1 = wss_bits[p[i] & 7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) int b2 = wss_bits[(p[i] >> 3) & 7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (b1 == b2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) wss |= b2 << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) parity = wss & 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) parity ^= parity >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) parity ^= parity >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (!(parity & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return wss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) u32 acpf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) u32 acni;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) u32 hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) u64 f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) u8 acc = 0; /* reg 0x3a, audio clock control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* Checks for chips that don't have audio clock (saa7111, saa7113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (freq < 32000 || freq > 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* hz is the refresh rate times 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) acpf = (25600 * freq) / hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* acni = (256 * freq * 2^23) / crystal_frequency =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) (freq * 2^(8+23)) / crystal_frequency =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) (freq << 31) / crystal_frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) f = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) f = f << 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) do_div(f, state->crystal_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) acni = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (state->ucgc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) acpf = acpf * state->cgcdiv / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) acni = acni * state->cgcdiv / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) acc = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (state->cgcdiv == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) acc |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (state->apll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) acc |= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (state->double_asclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) acpf <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) acni <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) (acpf >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) (acpf >> 16) & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) state->audclk_freq = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct v4l2_subdev *sd = to_sd(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) case V4L2_CID_CHROMA_AGC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* chroma gain cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (state->agc->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) state->gain->val =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct v4l2_subdev *sd = to_sd(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) case V4L2_CID_HUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) case V4L2_CID_CHROMA_AGC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* chroma gain cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (state->agc->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int HPSC, HFSC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int VSCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) int is_50hz = state->std & V4L2_STD_625_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int Vsrc = is_50hz ? 576 : 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /* FIXME need better bounds checking here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if ((width < 1) || (width > 1440))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if ((height < 1) || (height > Vsrc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* Decoder only supports 720 columns and 480 or 576 lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (width != 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (height != Vsrc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) state->width = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) state->height = height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* probably have a valid size, let's set it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /* Set output width/height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) (u8) (width & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) (u8) ((width >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* Vertical Scaling uses height/2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) res = height / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* On 60Hz, it is using a higher Vertical Output Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (!is_50hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) res += (VRES_60HZ - 480) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /* height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) (u8) (res & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) (u8) ((res >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* Scaling settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* Hprescaler is floor(inres/outres) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) HPSC = (int)(720 / width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /* 0 is not allowed (div. by zero) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) HPSC = HPSC ? HPSC : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) HFSC = (int)((1024 * 720) / (HPSC * width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* FIXME hardcodes to "Task B"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * write H prescaler integer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) (u8) (HPSC & 0x3f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* write H fine-scaling (luminance) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) (u8) (HFSC & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) (u8) ((HFSC >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /* write H fine-scaling (chrominance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * must be lum/2, so i'll just bitshift :) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) (u8) ((HFSC >> 1) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) (u8) ((HFSC >> 9) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) VSCY = (int)((1024 * Vsrc) / height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* Correct Contrast and Luminance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) (u8) (64 * 1024 / VSCY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) (u8) (64 * 1024 / VSCY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* write V fine-scaling (luminance) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) (u8) (VSCY & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) (u8) ((VSCY >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /* write V fine-scaling (chrominance) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) (u8) (VSCY & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) (u8) ((VSCY >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* Activates task "B" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) saa711x_write(sd, R_80_GLOBAL_CNTL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) /* Prevent unnecessary standard changes. During a standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) change the I-Port is temporarily disabled. Any devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) reading from that port can get confused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) Note that s_std is also used to switch from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) radio to TV mode, so if a s_std is broadcast to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) all I2C devices then you do not want to have an unwanted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) side-effect here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (std == state->std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) state->std = std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (std & V4L2_STD_525_60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (state->ident == GM7113C) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) reg |= SAA7113_R_08_FSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) saa711x_write(sd, R_08_SYNC_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) saa711x_writeregs(sd, saa7115_cfg_60hz_video);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) saa711x_set_size(sd, 720, 480);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (state->ident == GM7113C) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) saa711x_write(sd, R_08_SYNC_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) saa711x_writeregs(sd, saa7115_cfg_50hz_video);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) saa711x_set_size(sd, 720, 576);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* Register 0E - Bits D6-D4 on NO-AUTO mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) (SAA7111 and SAA7113 doesn't have auto mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 50 Hz / 625 lines 60 Hz / 525 lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 011 NTSC N (3.58MHz) PAL M (3.58MHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 100 reserved NTSC-Japan (3.58MHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (state->ident <= SAA7113 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) state->ident == GM7113C) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (std == V4L2_STD_PAL_M) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) reg |= 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) } else if (std == V4L2_STD_PAL_Nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) reg |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) } else if (std == V4L2_STD_PAL_60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) reg |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) } else if (std == V4L2_STD_NTSC_M_JP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) reg |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) } else if (std & V4L2_STD_SECAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) reg |= 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* restart task B if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (taskb && state->ident == SAA7114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) saa711x_writeregs(sd, saa7115_cfg_vbi_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* switch audio mode too! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) saa711x_s_clock_freq(sd, state->audclk_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* setup the sliced VBI lcr registers according to the sliced VBI format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) int is_50hz = (state->std & V4L2_STD_625_50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) u8 lcr[24];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) int i, x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) #if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /* saa7113/7114/7118 VBI support are experimental */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* SAA7113 and SAA7118 also should support VBI - Need testing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (state->ident != SAA7115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) for (i = 0; i <= 23; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) lcr[i] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (fmt == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /* raw VBI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (is_50hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) for (i = 6; i <= 23; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) lcr[i] = 0xdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) for (i = 10; i <= 21; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) lcr[i] = 0xdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* sliced VBI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* first clear lines that cannot be captured */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (is_50hz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) for (i = 0; i <= 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) fmt->service_lines[0][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) fmt->service_lines[1][i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) for (i = 0; i <= 9; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) fmt->service_lines[0][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) fmt->service_lines[1][i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) for (i = 22; i <= 23; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) fmt->service_lines[0][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) fmt->service_lines[1][i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /* Now set the lcr values according to the specified service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) for (i = 6; i <= 23; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) lcr[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) for (x = 0; x <= 1; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) switch (fmt->service_lines[1-x][i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) lcr[i] |= 0xf << (4 * x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) case V4L2_SLICED_TELETEXT_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) lcr[i] |= 1 << (4 * x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) case V4L2_SLICED_CAPTION_525:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) lcr[i] |= 4 << (4 * x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) case V4L2_SLICED_WSS_625:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) lcr[i] |= 5 << (4 * x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) case V4L2_SLICED_VPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) lcr[i] |= 7 << (4 * x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* write the lcr registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) for (i = 2; i <= 23; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /* enable/disable raw VBI capturing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) saa711x_writeregs(sd, fmt == NULL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) saa7115_cfg_vbi_on :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) saa7115_cfg_vbi_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static u16 lcr2vbi[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 0, V4L2_SLICED_CAPTION_525, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) V4L2_SLICED_WSS_625, 0, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 0, 0, 0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) sliced->service_set = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* done if using raw VBI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (i = 2; i <= 23; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) sliced->service_lines[0][i] = lcr2vbi[v >> 4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) sliced->service_set |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) sliced->service_lines[0][i] | sliced->service_lines[1][i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) saa711x_set_lcr(sd, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) saa711x_set_lcr(sd, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static int saa711x_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) struct v4l2_mbus_framefmt *fmt = &format->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) fmt->field = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (format->which == V4L2_SUBDEV_FORMAT_TRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return saa711x_set_size(sd, fmt->width, fmt->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /* Decode the sliced VBI data stream as created by the saa7115.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) The format is described in the saa7115 datasheet in Tables 25 and 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) and in Figure 33.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) The current implementation uses SAV/EAV codes and not the ancillary data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) static const char vbi_no_data_pattern[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) u8 *p = vbi->p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) u32 wss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int id1, id2; /* the ID1 and ID2 bytes from the internal header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) vbi->type = 0; /* mark result as a failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) id1 = p[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) id2 = p[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /* Note: the field bit is inverted for 60 Hz video */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (state->std & V4L2_STD_525_60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) id1 ^= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) /* Skip internal header, p now points to the start of the payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) vbi->p = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* calculate field and line number of the VBI packet (1-23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) vbi->is_second_field = ((id1 & 0x40) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) vbi->line = (id1 & 0x3f) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) vbi->line |= (id2 & 0x70) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* Obtain data type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) id2 &= 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* If the VBI slicer does not detect any signal it will fill up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) the payload buffer with 0xa0 bytes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) /* decode payloads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) switch (id2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) vbi->type = V4L2_SLICED_TELETEXT_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) vbi->type = V4L2_SLICED_CAPTION_525;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) wss = saa711x_decode_wss(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (wss == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) p[0] = wss & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) p[1] = wss >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) vbi->type = V4L2_SLICED_WSS_625;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (saa711x_decode_vps(p, p) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) vbi->type = V4L2_SLICED_VPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /* ============ SAA7115 AUDIO settings (end) ============= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (state->radio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) state->radio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) saa711x_set_v4lstd(sd, std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) static int saa711x_s_radio(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) state->radio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) static int saa711x_s_routing(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) u32 input, u32 output, u32 config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) input, output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /* saa7111/3 does not have these inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if ((state->ident <= SAA7113 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) state->ident == GM7113C) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) (input == SAA7115_COMPOSITE4 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) input == SAA7115_COMPOSITE5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (input > SAA7115_SVIDEO3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (state->input == input && state->output == output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) state->input = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /* saa7111 has slightly different input numbering */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (state->ident <= SAA7111A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (input >= SAA7115_COMPOSITE4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) input -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) /* saa7111 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) saa711x_write(sd, R_10_CHROMA_CNTL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) ((output & 0xc0) ^ 0x40));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) ((output & 2) ? 0x0a : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /* select mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) saa711x_write(sd, R_02_INPUT_CNTL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /* bypass chrominance trap for S-Video modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) saa711x_write(sd, R_09_LUMA_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) state->output = output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (state->ident == SAA7114 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) state->ident == SAA7115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) (state->output & 0x01));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (state->ident > SAA7111A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (config & SAA7115_IDQ_IS_DEFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (state->ident > SAA7111A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) (val ? 0x80 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) v4l2_dbg(1, debug, sd, "%s output\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) enable ? "enable" : "disable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (state->enable == enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) state->enable = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) state->crystal_freq = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) state->apll = flags & SAA7115_FREQ_FL_APLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) saa711x_s_clock_freq(sd, state->audclk_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) v4l2_dbg(1, debug, sd, "decoder RESET\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /* Note: the internal field ID is inverted for NTSC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) so data->field 0 maps to the saa7115 even field,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) whereas for PAL it maps to the saa7115 odd field. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) switch (data->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) case V4L2_SLICED_WSS_625:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (saa711x_read(sd, 0x6b) & 0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) data->data[0] = saa711x_read(sd, 0x6c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) data->data[1] = saa711x_read(sd, 0x6d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) case V4L2_SLICED_CAPTION_525:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (data->field == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) /* CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (saa711x_read(sd, 0x66) & 0x30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) data->data[0] = saa711x_read(sd, 0x69);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) data->data[1] = saa711x_read(sd, 0x6a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) /* XDS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if (saa711x_read(sd, 0x66) & 0xc0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) data->data[0] = saa711x_read(sd, 0x67);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) data->data[1] = saa711x_read(sd, 0x68);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) int reg1f, reg1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * The V4L2 core already initializes std with all supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) * Standards. All driver needs to do is to mask it, to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) * standards that don't apply from the mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (state->ident == SAA7115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) switch (reg1e & 0x03) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) *std &= V4L2_STD_NTSC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) * V4L2_STD_PAL just cover the european PAL standards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) * This is wrong, as the device could also be using an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * other PAL standard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) V4L2_STD_PAL_M | V4L2_STD_PAL_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) *std &= V4L2_STD_SECAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) *std = V4L2_STD_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) /* Can't detect anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* horizontal/vertical not locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (reg1f & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) *std = V4L2_STD_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) goto ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (reg1f & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) *std &= V4L2_STD_525_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) *std &= V4L2_STD_625_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) int reg1e = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) int reg1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) *status = V4L2_IN_ST_NO_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) if (state->ident == SAA7115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) reg->val = saa711x_read(sd, reg->reg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) reg->size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) static int saa711x_log_status(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) struct saa711x_state *state = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) int reg1e, reg1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) int signalOk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) int vcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (state->ident != SAA7115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) /* status for the saa7114 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) signalOk = (reg1f & 0xc1) == 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) /* status for the saa7115 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) vcr = !(reg1f & 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) if (state->input >= 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) v4l2_info(sd, "Input: Composite %d\n", state->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) switch (reg1e & 0x03) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) v4l2_info(sd, "Detected format: NTSC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) v4l2_info(sd, "Detected format: PAL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) v4l2_info(sd, "Detected format: SECAM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) v4l2_info(sd, "Detected format: BW/No color\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) .s_ctrl = saa711x_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) .g_volatile_ctrl = saa711x_g_volatile_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) static const struct v4l2_subdev_core_ops saa711x_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) .log_status = saa711x_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) .reset = saa711x_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) .s_gpio = saa711x_s_gpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) .g_register = saa711x_g_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) .s_register = saa711x_s_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) .s_radio = saa711x_s_radio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) .g_tuner = saa711x_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) .s_clock_freq = saa711x_s_clock_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) static const struct v4l2_subdev_video_ops saa711x_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) .s_std = saa711x_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) .s_routing = saa711x_s_routing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) .s_crystal_freq = saa711x_s_crystal_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) .s_stream = saa711x_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) .querystd = saa711x_querystd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) .g_input_status = saa711x_g_input_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) .g_vbi_data = saa711x_g_vbi_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) .decode_vbi_line = saa711x_decode_vbi_line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) .g_sliced_fmt = saa711x_g_sliced_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) .s_sliced_fmt = saa711x_s_sliced_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) .s_raw_fmt = saa711x_s_raw_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) static const struct v4l2_subdev_pad_ops saa711x_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) .set_fmt = saa711x_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) static const struct v4l2_subdev_ops saa711x_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) .core = &saa711x_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) .tuner = &saa711x_tuner_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) .audio = &saa711x_audio_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) .video = &saa711x_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) .vbi = &saa711x_vbi_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) .pad = &saa711x_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) #define CHIP_VER_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) static void saa711x_write_platform_data(struct saa711x_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) struct saa7115_platform_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) struct v4l2_subdev *sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) u8 work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (state->ident != GM7113C &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) state->ident != SAA7113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (data->saa7113_r08_htc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) work = saa711x_read(sd, R_08_SYNC_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) work &= ~SAA7113_R_08_HTC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) saa711x_write(sd, R_08_SYNC_CNTL, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) if (data->saa7113_r10_vrln) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) work &= ~SAA7113_R_10_VRLN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (*data->saa7113_r10_vrln)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) work |= (1 << SAA7113_R_10_VRLN_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (data->saa7113_r10_ofts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) work &= ~SAA7113_R_10_OFTS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) if (data->saa7113_r12_rts0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) work &= ~SAA7113_R_12_RTS0_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) /* According to the datasheet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) * SAA7113_RTS_DOT_IN should only be used on RTS1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (data->saa7113_r12_rts1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) work &= ~SAA7113_R_12_RTS1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) if (data->saa7113_r13_adlsb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) work &= ~SAA7113_R_13_ADLSB_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (*data->saa7113_r13_adlsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) work |= (1 << SAA7113_R_13_ADLSB_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) * saa711x_detect_chip - Detects the saa711x (or clone) variant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) * @client: I2C client structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) * @id: I2C device ID structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) * @name: Name of the device to be filled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) * Detects the Philips/NXP saa711x chip, or some clone of it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) * the analog demod.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) * If the tuner is not found, it returns -ENODEV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) * If auto-detection is disabled and the tuner doesn't match what it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) * required, it returns -EINVAL and fills 'name'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * If the chip is found, it returns the chip ID and fills 'name'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) static int saa711x_detect_chip(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) const struct i2c_device_id *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) char chip_ver[CHIP_VER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) char chip_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) int autodetect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) autodetect = !id || id->driver_data == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) /* Read the chip version register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) for (i = 0; i < CHIP_VER_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) i2c_smbus_write_byte_data(client, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) name[i] = (chip_ver[i] & 0x0f) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) if (name[i] > '9')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) name[i] += 'a' - '9' - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) name[i] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) /* Check if it is a Philips/NXP chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (!memcmp(name + 1, "f711", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) chip_id = name[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (!autodetect && strcmp(name, id->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) switch (chip_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (chip_ver[0] & 0xf0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) v4l_info(client, "saa7111a variant found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return SAA7111A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return SAA7111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) case '3':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) return SAA7113;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) case '4':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) return SAA7114;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) case '5':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) return SAA7115;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) case '8':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) return SAA7118;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) v4l2_info(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) return SAA7111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) /* Check if it is a gm7113c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (!memcmp(name, "0000", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) chip_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) chip_id = chip_id << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) * Note: From the datasheet, only versions 1 and 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) * exists. However, tests on a device labeled as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) * "GM7113C 1145" returned "10" on all 16 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) * version (reg 0x00) reads. So, we need to also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) * accept at least version 0. For now, let's just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) * assume that a device that returns "0000" for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) * the lower nibble is a gm7113c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) strscpy(name, "gm7113c", CHIP_VER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (!autodetect && strcmp(name, id->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) v4l_dbg(1, debug, client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) "It seems to be a %s chip (%*ph) @ 0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) name, 16, chip_ver, client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return GM7113C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) /* Check if it is a CJC7113 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) strscpy(name, "cjc7113", CHIP_VER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if (!autodetect && strcmp(name, id->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) v4l_dbg(1, debug, client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) "It seems to be a %s chip (%*ph) @ 0x%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) name, 16, chip_ver, client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) /* CJC7113 seems to be SAA7113-compatible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) return SAA7113;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) /* Chip was not discovered. Return its ID and don't bind */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 16, chip_ver, client->addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) static int saa711x_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) struct saa711x_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) struct v4l2_ctrl_handler *hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) struct saa7115_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) int ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) char name[CHIP_VER_SIZE + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) /* Check if the adapter supports the needed features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) ident = saa711x_detect_chip(client, id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) if (ident == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) /* Chip exists, but doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) v4l_warn(client, "found %s while %s was expected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) name, id->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) if (ident < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) return ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) strscpy(client->name, name, sizeof(client->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) sd = &state->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) state->pads[SAA711X_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) state->pads[SAA711X_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) state->pads[SAA711X_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) state->pads[SAA711X_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) ret = media_entity_pads_init(&sd->entity, SAA711X_NUM_PADS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) state->pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) v4l_info(client, "%s found @ 0x%x (%s)\n", name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) client->addr << 1, client->adapter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) hdl = &state->hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) v4l2_ctrl_handler_init(hdl, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) /* add in ascending ID order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) V4L2_CID_CONTRAST, 0, 127, 1, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) V4L2_CID_SATURATION, 0, 127, 1, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) V4L2_CID_HUE, -128, 127, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) sd->ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) int err = hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) state->input = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) state->output = SAA7115_IPORT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) state->enable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) state->radio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) state->ident = ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) state->audclk_freq = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) v4l2_dbg(1, debug, sd, "writing init values\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) /* init to 60hz/48khz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) switch (state->ident) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) case SAA7111:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) case SAA7111A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) saa711x_writeregs(sd, saa7111_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) case GM7113C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) saa711x_writeregs(sd, gm7113c_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) case SAA7113:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) if (pdata && pdata->saa7113_force_gm7113c_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) saa711x_writeregs(sd, gm7113c_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) saa711x_writeregs(sd, saa7113_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) saa711x_writeregs(sd, saa7115_init_auto_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (state->ident > SAA7111A && state->ident != GM7113C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) saa711x_writeregs(sd, saa7115_init_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) if (pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) saa711x_write_platform_data(state, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) v4l2_ctrl_handler_setup(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) static int saa711x_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) v4l2_device_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) v4l2_ctrl_handler_free(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) static const struct i2c_device_id saa711x_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) { "saa7115_auto", 1 }, /* autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) { "saa7111", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) { "saa7113", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) { "saa7114", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) { "saa7115", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) { "saa7118", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) { "gm7113c", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) MODULE_DEVICE_TABLE(i2c, saa711x_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) static struct i2c_driver saa711x_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) .name = "saa7115",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) .probe = saa711x_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) .remove = saa711x_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) .id_table = saa711x_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) module_i2c_driver(saa711x_driver);