diff options
author | Malcolm Priestley <tvboxspy@gmail.com> | 2013-12-24 11:17:12 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-01-07 06:35:58 -0500 |
commit | 06af15d1b6f45c60358feab88004472e5428f01c (patch) | |
tree | 57ec8127c9cb1a898951179a75d9ac7a0b8729b8 /drivers/media | |
parent | 58f087c9b670ea7001d640fadbf7e4e91e739d6b (diff) |
[media] m88rs2000: add m88rs2000_set_carrieroffset
Set the carrier offset correctly using the default mclk values.
Add function m88rs2000_get_mclk to calculate the mclk value
against crystal frequency which will later be used for
other functions.
Add function m88rs2000_set_carrieroffset to calculate
and set the offset value.
variable offset becomes a signed value.
Register 0x86 is set the appropriate value according to
remainder value of frequency % 192857 calculation as
shown.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
Cc: stable@vger.kernel.org # v3.9+
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.c | 77 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/m88rs2000.h | 2 |
2 files changed, 59 insertions, 20 deletions
diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 4da5272075cb..8091653e8864 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c | |||
@@ -110,6 +110,52 @@ static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 reg) | |||
110 | return b1[0]; | 110 | return b1[0]; |
111 | } | 111 | } |
112 | 112 | ||
113 | static u32 m88rs2000_get_mclk(struct dvb_frontend *fe) | ||
114 | { | ||
115 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
116 | u32 mclk; | ||
117 | u8 reg; | ||
118 | /* Must not be 0x00 or 0xff */ | ||
119 | reg = m88rs2000_readreg(state, 0x86); | ||
120 | if (!reg || reg == 0xff) | ||
121 | return 0; | ||
122 | |||
123 | reg /= 2; | ||
124 | reg += 1; | ||
125 | |||
126 | mclk = (u32)(reg * RS2000_FE_CRYSTAL_KHZ + 28 / 2) / 28; | ||
127 | |||
128 | return mclk; | ||
129 | } | ||
130 | |||
131 | static int m88rs2000_set_carrieroffset(struct dvb_frontend *fe, s16 offset) | ||
132 | { | ||
133 | struct m88rs2000_state *state = fe->demodulator_priv; | ||
134 | u32 mclk; | ||
135 | s32 tmp; | ||
136 | u8 reg; | ||
137 | int ret; | ||
138 | |||
139 | mclk = m88rs2000_get_mclk(fe); | ||
140 | if (!mclk) | ||
141 | return -EINVAL; | ||
142 | |||
143 | tmp = (offset * 4096 + (s32)mclk / 2) / (s32)mclk; | ||
144 | if (tmp < 0) | ||
145 | tmp += 4096; | ||
146 | |||
147 | /* Carrier Offset */ | ||
148 | ret = m88rs2000_writereg(state, 0x9c, (u8)(tmp >> 4)); | ||
149 | |||
150 | reg = m88rs2000_readreg(state, 0x9d); | ||
151 | reg &= 0xf; | ||
152 | reg |= (u8)(tmp & 0xf) << 4; | ||
153 | |||
154 | ret |= m88rs2000_writereg(state, 0x9d, reg); | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | |||
113 | static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) | 159 | static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate) |
114 | { | 160 | { |
115 | struct m88rs2000_state *state = fe->demodulator_priv; | 161 | struct m88rs2000_state *state = fe->demodulator_priv; |
@@ -540,9 +586,8 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
540 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 586 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
541 | fe_status_t status; | 587 | fe_status_t status; |
542 | int i, ret = 0; | 588 | int i, ret = 0; |
543 | s32 tmp; | ||
544 | u32 tuner_freq; | 589 | u32 tuner_freq; |
545 | u16 offset = 0; | 590 | s16 offset = 0; |
546 | u8 reg; | 591 | u8 reg; |
547 | 592 | ||
548 | state->no_lock_count = 0; | 593 | state->no_lock_count = 0; |
@@ -567,26 +612,18 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) | |||
567 | if (ret < 0) | 612 | if (ret < 0) |
568 | return -ENODEV; | 613 | return -ENODEV; |
569 | 614 | ||
570 | offset = tuner_freq - c->frequency; | 615 | offset = (s16)((s32)tuner_freq - c->frequency); |
571 | 616 | ||
572 | /* calculate offset assuming 96000kHz*/ | 617 | /* default mclk value 96.4285 * 2 * 1000 = 192857 */ |
573 | tmp = offset; | 618 | if (((c->frequency % 192857) >= (192857 - 3000)) || |
574 | tmp *= 65536; | 619 | (c->frequency % 192857) <= 3000) |
575 | 620 | ret = m88rs2000_writereg(state, 0x86, 0xc2); | |
576 | tmp = (2 * tmp + 96000) / (2 * 96000); | 621 | else |
577 | if (tmp < 0) | 622 | ret = m88rs2000_writereg(state, 0x86, 0xc6); |
578 | tmp += 65536; | ||
579 | |||
580 | offset = tmp & 0xffff; | ||
581 | |||
582 | ret = m88rs2000_writereg(state, 0x9a, 0x30); | ||
583 | /* Unknown usually 0xc6 sometimes 0xc1 */ | ||
584 | reg = m88rs2000_readreg(state, 0x86); | ||
585 | ret |= m88rs2000_writereg(state, 0x86, reg); | ||
586 | /* Offset lower nibble always 0 */ | ||
587 | ret |= m88rs2000_writereg(state, 0x9c, (offset >> 8)); | ||
588 | ret |= m88rs2000_writereg(state, 0x9d, offset & 0xf0); | ||
589 | 623 | ||
624 | ret |= m88rs2000_set_carrieroffset(fe, offset); | ||
625 | if (ret < 0) | ||
626 | return -ENODEV; | ||
590 | 627 | ||
591 | /* Reset Demod */ | 628 | /* Reset Demod */ |
592 | ret = m88rs2000_tab_set(state, fe_reset); | 629 | ret = m88rs2000_tab_set(state, fe_reset); |
diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h index 14ce31e76ae6..0a50ea90736b 100644 --- a/drivers/media/dvb-frontends/m88rs2000.h +++ b/drivers/media/dvb-frontends/m88rs2000.h | |||
@@ -53,6 +53,8 @@ static inline struct dvb_frontend *m88rs2000_attach( | |||
53 | } | 53 | } |
54 | #endif /* CONFIG_DVB_M88RS2000 */ | 54 | #endif /* CONFIG_DVB_M88RS2000 */ |
55 | 55 | ||
56 | #define RS2000_FE_CRYSTAL_KHZ 27000 | ||
57 | |||
56 | enum { | 58 | enum { |
57 | DEMOD_WRITE = 0x1, | 59 | DEMOD_WRITE = 0x1, |
58 | WRITE_DELAY = 0x10, | 60 | WRITE_DELAY = 0x10, |