^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) Samsung S5H1411 VSB/QAM demodulator driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "s5h1411.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct s5h1411_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* configuration settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) const struct s5h1411_config *config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) enum fe_modulation current_modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int first_tune:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u32 current_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int if_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u8 inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define dprintk(arg...) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) printk(arg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Register values to initialise the demod, defaults to VSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct init_tab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u8 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) } init_tab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342c, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* VSB SNR lookup table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static struct vsb_snr_tab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) } vsb_snr_tab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { 0x39f, 300, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { 0x39b, 295, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) { 0x397, 290, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { 0x394, 285, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) { 0x38f, 280, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { 0x38b, 275, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) { 0x387, 270, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { 0x382, 265, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { 0x37d, 260, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { 0x377, 255, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { 0x370, 250, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { 0x36a, 245, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { 0x364, 240, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { 0x35b, 235, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { 0x353, 230, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { 0x349, 225, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { 0x340, 320, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { 0x337, 215, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { 0x327, 210, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { 0x31b, 205, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { 0x310, 200, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { 0x302, 195, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { 0x2f3, 190, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { 0x2e4, 185, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { 0x2d7, 180, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { 0x2cd, 175, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { 0x2bb, 170, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { 0x2a9, 165, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { 0x29e, 160, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { 0x284, 155, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { 0x27a, 150, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { 0x260, 145, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { 0x23a, 140, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { 0x224, 135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { 0x213, 130, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { 0x204, 125, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) { 0x1fe, 120, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) { 0, 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* QAM64 SNR lookup table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static struct qam64_snr_tab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) } qam64_snr_tab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { 0x0001, 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { 0x0af0, 300, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { 0x0d80, 290, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { 0x10a0, 280, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { 0x14b5, 270, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { 0x1590, 268, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { 0x1680, 266, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { 0x17b0, 264, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { 0x18c0, 262, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { 0x19b0, 260, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { 0x1ad0, 258, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { 0x1d00, 256, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { 0x1da0, 254, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { 0x1ef0, 252, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { 0x2050, 250, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { 0x20f0, 249, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { 0x21d0, 248, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { 0x22b0, 247, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { 0x23a0, 246, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { 0x2470, 245, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { 0x24f0, 244, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { 0x25a0, 243, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { 0x26c0, 242, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { 0x27b0, 241, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { 0x28d0, 240, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { 0x29b0, 239, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { 0x2ad0, 238, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { 0x2ba0, 237, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) { 0x2c80, 236, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { 0x2d20, 235, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) { 0x2e00, 234, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { 0x2f10, 233, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) { 0x3050, 232, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { 0x3190, 231, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) { 0x3300, 230, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { 0x3340, 229, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { 0x3200, 228, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) { 0x3550, 227, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) { 0x3610, 226, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) { 0x3600, 225, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { 0x3700, 224, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { 0x3800, 223, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { 0x3920, 222, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { 0x3a20, 221, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { 0x3b30, 220, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { 0x3d00, 219, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { 0x3e00, 218, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { 0x4000, 217, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) { 0x4100, 216, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { 0x4300, 215, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) { 0x4400, 214, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { 0x4600, 213, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) { 0x4700, 212, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) { 0x4800, 211, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) { 0x4a00, 210, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) { 0x4b00, 209, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) { 0x4d00, 208, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) { 0x4f00, 207, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) { 0x5050, 206, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) { 0x5200, 205, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) { 0x53c0, 204, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { 0x5450, 203, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { 0x5650, 202, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { 0x5820, 201, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { 0x6000, 200, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) { 0xffff, 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* QAM256 SNR lookup table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static struct qam256_snr_tab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) } qam256_snr_tab[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { 0x0001, 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { 0x0970, 400, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { 0x0a90, 390, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { 0x0b90, 380, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { 0x0d90, 370, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) { 0x0ff0, 360, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { 0x1240, 350, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { 0x1345, 348, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) { 0x13c0, 346, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) { 0x14c0, 344, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) { 0x1500, 342, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { 0x1610, 340, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { 0x1700, 338, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) { 0x1800, 336, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { 0x18b0, 334, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { 0x1900, 332, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { 0x1ab0, 330, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) { 0x1bc0, 328, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { 0x1cb0, 326, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { 0x1db0, 324, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { 0x1eb0, 322, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) { 0x2030, 320, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) { 0x2200, 318, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) { 0x2280, 316, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) { 0x2410, 314, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) { 0x25b0, 312, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { 0x27a0, 310, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { 0x2840, 308, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) { 0x29d0, 306, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { 0x2b10, 304, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { 0x2d30, 302, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) { 0x2f20, 300, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { 0x30c0, 298, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { 0x3260, 297, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { 0x32c0, 296, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { 0x3300, 295, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { 0x33b0, 294, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { 0x34b0, 293, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { 0x35a0, 292, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { 0x3650, 291, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { 0x3800, 290, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { 0x3900, 289, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { 0x3a50, 288, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { 0x3b30, 287, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { 0x3cb0, 286, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) { 0x3e20, 285, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) { 0x3fa0, 284, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { 0x40a0, 283, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { 0x41c0, 282, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) { 0x42f0, 281, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { 0x44a0, 280, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { 0x4600, 279, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { 0x47b0, 278, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { 0x4900, 277, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { 0x4a00, 276, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { 0x4ba0, 275, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { 0x4d00, 274, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { 0x4f00, 273, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { 0x5000, 272, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) { 0x51f0, 272, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { 0x53a0, 270, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { 0x5520, 269, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) { 0x5700, 268, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { 0x5800, 267, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) { 0x5a00, 266, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) { 0x5c00, 265, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) { 0x5d00, 264, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { 0x5f00, 263, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { 0x6000, 262, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { 0x6200, 261, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) { 0x6400, 260, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) { 0xffff, 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* 8 bit registers, 16 bit values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int s5h1411_writereg(struct s5h1411_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u8 addr, u8 reg, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u8 buf[] = { reg, data >> 8, data & 0xff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ret = i2c_transfer(state->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) __func__, addr, reg, data, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return (ret != 1) ? -1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) u8 b0[] = { reg };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) u8 b1[] = { 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ret = i2c_transfer(state->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (ret != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) printk(KERN_ERR "%s: readreg error (ret == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return (b1[0] << 8) | b1[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int s5h1411_softreset(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) dprintk("%s(%d KHz)\n", __func__, KHz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) switch (KHz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) case 3250:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case 3500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case 4000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) __func__, KHz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) case 5380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) case 44000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) state->if_freq = KHz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dprintk("%s(%d)\n", __func__, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case S5H1411_MPEGTIMING_CONTINUOUS_INVERTING_CLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) val |= 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) val |= 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) case S5H1411_MPEGTIMING_NONCONTINUOUS_INVERTING_CLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) val |= 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case S5H1411_MPEGTIMING_NONCONTINUOUS_NONINVERTING_CLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) val |= 0x3000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Configure MPEG Signal Timing charactistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) dprintk("%s(%d)\n", __func__, inversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (inversion == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) val |= 0x1000; /* Inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) state->inversion = inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dprintk("%s(%d)\n", __func__, serial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (serial == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) val |= 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int s5h1411_enable_modulation(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) enum fe_modulation m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) dprintk("%s(0x%08x)\n", __func__, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if ((state->first_tune == 0) && (m == state->current_modulation)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dprintk("%s() Already at desired modulation. Skipping...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) switch (m) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) dprintk("%s() VSB_8\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) s5h1411_set_if_freq(fe, state->config->vsb_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) case QAM_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dprintk("%s() QAM_AUTO (64/256)\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) s5h1411_set_if_freq(fe, state->config->qam_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) dprintk("%s() Invalid modulation\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) state->current_modulation = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) state->first_tune = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) s5h1411_softreset(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) dprintk("%s(%d)\n", __func__, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) dprintk("%s(%d)\n", __func__, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) val | 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) dprintk("%s(%d)\n", __func__, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) s5h1411_softreset(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static int s5h1411_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return s5h1411_set_powerstate(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static int s5h1411_register_reset(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static int s5h1411_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) dprintk("%s(frequency=%d)\n", __func__, p->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) s5h1411_softreset(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) state->current_frequency = p->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) s5h1411_enable_modulation(fe, p->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (fe->ops.tuner_ops.set_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* Issue a reset to the demod so it knows to resync against the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) newly tuned frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) s5h1411_softreset(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* Reset the demod hardware and reset all of the configuration registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) to a default state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static int s5h1411_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) s5h1411_set_powerstate(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) s5h1411_register_reset(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) for (i = 0; i < ARRAY_SIZE(init_tab); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) s5h1411_writereg(state, init_tab[i].addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) init_tab[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) init_tab[i].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* The datasheet says that after initialisation, VSB is default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) state->current_modulation = VSB_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* Although the datasheet says it's in VSB, empirical evidence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) shows problems getting lock on the first tuning request. Make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) sure we call enable_modulation the first time around */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) state->first_tune = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* Serial */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) s5h1411_set_serialmode(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* Parallel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) s5h1411_set_serialmode(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) s5h1411_set_spectralinversion(fe, state->config->inversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) s5h1411_set_if_freq(fe, state->config->vsb_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) s5h1411_set_gpio(fe, state->config->gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) s5h1411_softreset(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* Note: Leaving the I2C gate closed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) s5h1411_i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static int s5h1411_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) u32 tuner_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /* Register F2 bit 15 = Master Lock, removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) switch (state->current_modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (reg & 0x10) /* QAM FEC Lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) *status |= FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (reg & 0x100) /* QAM EQ Lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (reg & 0x1000) /* FEC Lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) *status |= FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (reg & 0x2000) /* EQ Lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x53);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (reg & 0x1) /* AFC Lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) switch (state->config->status_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case S5H1411_DEMODLOCKING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (*status & FE_HAS_VITERBI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case S5H1411_TUNERLOCKING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* Get the tuner status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (fe->ops.tuner_ops.get_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) fe->ops.tuner_ops.get_status(fe, &tuner_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (tuner_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) dprintk("%s() status 0x%08x\n", __func__, *status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int i, ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (v < qam256_snr_tab[i].val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) *snr = qam256_snr_tab[i].data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int i, ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (v < qam64_snr_tab[i].val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) *snr = qam64_snr_tab[i].data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) int i, ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (v > vsb_snr_tab[i].val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) *snr = vsb_snr_tab[i].data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dprintk("%s() snr=%d\n", __func__, *snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dprintk("%s()\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) switch (state->current_modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return s5h1411_qam64_lookup_snr(fe, snr, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return s5h1411_qam256_lookup_snr(fe, snr, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 0xf2) & 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return s5h1411_vsb_lookup_snr(fe, snr, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) u16 *signal_strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* borrowed from lgdt330x.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * Calculate strength from SNR up to 35dB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * Even though the SNR can go higher than 35dB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * there is some comfort factor in having a range of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * strong signals that can show at 100%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) u16 snr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) int ret = s5h1411_read_snr(fe, &snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) *signal_strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (0 == ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* The following calculation method was chosen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * purely for the sake of code re-use from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * other demod drivers that use this method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* Convert from SNR in dB * 10 to 8.24 fixed-point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) tmp = (snr * ((1 << 24) / 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* Convert from 8.24 fixed-point to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * scale the range 0 - 35*2^24 into 0 - 65535*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (tmp >= 8960 * 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *signal_strength = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) *signal_strength = tmp / 8960;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return s5h1411_read_ucblocks(fe, ber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static int s5h1411_get_frontend(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) p->frequency = state->current_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) p->modulation = state->current_modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct dvb_frontend_tune_settings *tune)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) tune->min_delay_ms = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static void s5h1411_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct s5h1411_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static const struct dvb_frontend_ops s5h1411_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) struct i2c_adapter *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct s5h1411_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* setup the state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) state->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) state->current_modulation = VSB_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) state->inversion = state->config->inversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* check if the demod exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (reg != 0x0066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) memcpy(&state->frontend.ops, &s5h1411_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (s5h1411_init(&state->frontend) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) printk(KERN_ERR "%s: Failed to initialize correctly\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* Note: Leaving the I2C gate open here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* Put the device into low-power mode until first use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) s5h1411_set_powerstate(&state->frontend, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) EXPORT_SYMBOL(s5h1411_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static const struct dvb_frontend_ops s5h1411_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) .name = "Samsung S5H1411 QAM/8VSB Frontend",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .frequency_min_hz = 54 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .frequency_max_hz = 858 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .frequency_stepsize_hz = 62500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .init = s5h1411_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .sleep = s5h1411_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .i2c_gate_ctrl = s5h1411_i2c_gate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .set_frontend = s5h1411_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .get_frontend = s5h1411_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .get_tune_settings = s5h1411_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .read_status = s5h1411_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .read_ber = s5h1411_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .read_signal_strength = s5h1411_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .read_snr = s5h1411_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .read_ucblocks = s5h1411_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .release = s5h1411_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) MODULE_PARM_DESC(debug, "Enable verbose debug messages");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) MODULE_AUTHOR("Steven Toth");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) MODULE_LICENSE("GPL");