diff options
Diffstat (limited to 'drivers/media/dvb/frontends/cx24123.c')
-rw-r--r-- | drivers/media/dvb/frontends/cx24123.c | 195 |
1 files changed, 51 insertions, 144 deletions
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 691dc840dcc0..f2f795cba56a 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c | |||
@@ -41,14 +41,12 @@ static int debug; | |||
41 | struct cx24123_state | 41 | struct cx24123_state |
42 | { | 42 | { |
43 | struct i2c_adapter* i2c; | 43 | struct i2c_adapter* i2c; |
44 | struct dvb_frontend_ops ops; | ||
45 | const struct cx24123_config* config; | 44 | const struct cx24123_config* config; |
46 | 45 | ||
47 | struct dvb_frontend frontend; | 46 | struct dvb_frontend frontend; |
48 | 47 | ||
49 | u32 lastber; | 48 | u32 lastber; |
50 | u16 snr; | 49 | u16 snr; |
51 | u8 lnbreg; | ||
52 | 50 | ||
53 | /* Some PLL specifics for tuning */ | 51 | /* Some PLL specifics for tuning */ |
54 | u32 VCAarg; | 52 | u32 VCAarg; |
@@ -249,29 +247,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data) | |||
249 | return 0; | 247 | return 0; |
250 | } | 248 | } |
251 | 249 | ||
252 | static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data) | ||
253 | { | ||
254 | u8 buf[] = { reg, data }; | ||
255 | /* fixme: put the intersil addr int the config */ | ||
256 | struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; | ||
257 | int err; | ||
258 | |||
259 | if (debug>1) | ||
260 | printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n", | ||
261 | __FUNCTION__,reg, data); | ||
262 | |||
263 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | ||
264 | printk("%s: writelnbreg error (err == %i, reg == 0x%02x," | ||
265 | " data == 0x%02x)\n", __FUNCTION__, err, reg, data); | ||
266 | return -EREMOTEIO; | ||
267 | } | ||
268 | |||
269 | /* cache the write, no way to read back */ | ||
270 | state->lnbreg = data; | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int cx24123_readreg(struct cx24123_state* state, u8 reg) | 250 | static int cx24123_readreg(struct cx24123_state* state, u8 reg) |
276 | { | 251 | { |
277 | int ret; | 252 | int ret; |
@@ -295,11 +270,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg) | |||
295 | return b1[0]; | 270 | return b1[0]; |
296 | } | 271 | } |
297 | 272 | ||
298 | static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg) | ||
299 | { | ||
300 | return state->lnbreg; | ||
301 | } | ||
302 | |||
303 | static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) | 273 | static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) |
304 | { | 274 | { |
305 | u8 nom_reg = cx24123_readreg(state, 0x0e); | 275 | u8 nom_reg = cx24123_readreg(state, 0x0e); |
@@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) | |||
458 | u8 pll_mult; | 428 | u8 pll_mult; |
459 | 429 | ||
460 | /* check if symbol rate is within limits */ | 430 | /* check if symbol rate is within limits */ |
461 | if ((srate > state->ops.info.symbol_rate_max) || | 431 | if ((srate > state->frontend.ops.info.symbol_rate_max) || |
462 | (srate < state->ops.info.symbol_rate_min)) | 432 | (srate < state->frontend.ops.info.symbol_rate_min)) |
463 | return -EOPNOTSUPP;; | 433 | return -EOPNOTSUPP;; |
464 | 434 | ||
465 | /* choose the sampling rate high enough for the required operation, | 435 | /* choose the sampling rate high enough for the required operation, |
@@ -687,13 +657,6 @@ static int cx24123_initfe(struct dvb_frontend* fe) | |||
687 | for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) | 657 | for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) |
688 | cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); | 658 | cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); |
689 | 659 | ||
690 | if (state->config->pll_init) | ||
691 | state->config->pll_init(fe); | ||
692 | |||
693 | /* Configure the LNB for 14V */ | ||
694 | if (state->config->use_isl6421) | ||
695 | cx24123_writelnbreg(state, 0x0, 0x2a); | ||
696 | |||
697 | return 0; | 660 | return 0; |
698 | } | 661 | } |
699 | 662 | ||
@@ -702,50 +665,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage | |||
702 | struct cx24123_state *state = fe->demodulator_priv; | 665 | struct cx24123_state *state = fe->demodulator_priv; |
703 | u8 val; | 666 | u8 val; |
704 | 667 | ||
705 | switch (state->config->use_isl6421) { | 668 | val = cx24123_readreg(state, 0x29) & ~0x40; |
706 | |||
707 | case 1: | ||
708 | 669 | ||
709 | val = cx24123_readlnbreg(state, 0x0); | 670 | switch (voltage) { |
710 | 671 | case SEC_VOLTAGE_13: | |
711 | switch (voltage) { | 672 | dprintk("%s: setting voltage 13V\n", __FUNCTION__); |
712 | case SEC_VOLTAGE_13: | 673 | return cx24123_writereg(state, 0x29, val | 0x80); |
713 | dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__); | 674 | case SEC_VOLTAGE_18: |
714 | return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ | 675 | dprintk("%s: setting voltage 18V\n", __FUNCTION__); |
715 | case SEC_VOLTAGE_18: | 676 | return cx24123_writereg(state, 0x29, val & 0x7f); |
716 | dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__); | 677 | default: |
717 | return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ | 678 | return -EINVAL; |
718 | case SEC_VOLTAGE_OFF: | 679 | }; |
719 | dprintk("%s: isl5421 voltage off\n",__FUNCTION__); | ||
720 | return cx24123_writelnbreg(state, 0x0, val & 0x30); | ||
721 | default: | ||
722 | return -EINVAL; | ||
723 | }; | ||
724 | |||
725 | case 0: | ||
726 | |||
727 | val = cx24123_readreg(state, 0x29); | ||
728 | |||
729 | switch (voltage) { | ||
730 | case SEC_VOLTAGE_13: | ||
731 | dprintk("%s: setting voltage 13V\n", __FUNCTION__); | ||
732 | if (state->config->enable_lnb_voltage) | ||
733 | state->config->enable_lnb_voltage(fe, 1); | ||
734 | return cx24123_writereg(state, 0x29, val | 0x80); | ||
735 | case SEC_VOLTAGE_18: | ||
736 | dprintk("%s: setting voltage 18V\n", __FUNCTION__); | ||
737 | if (state->config->enable_lnb_voltage) | ||
738 | state->config->enable_lnb_voltage(fe, 1); | ||
739 | return cx24123_writereg(state, 0x29, val & 0x7f); | ||
740 | case SEC_VOLTAGE_OFF: | ||
741 | dprintk("%s: setting voltage off\n", __FUNCTION__); | ||
742 | if (state->config->enable_lnb_voltage) | ||
743 | state->config->enable_lnb_voltage(fe, 0); | ||
744 | return 0; | ||
745 | default: | ||
746 | return -EINVAL; | ||
747 | }; | ||
748 | } | ||
749 | 680 | ||
750 | return 0; | 681 | return 0; |
751 | } | 682 | } |
@@ -766,27 +697,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state) | |||
766 | static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) | 697 | static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) |
767 | { | 698 | { |
768 | struct cx24123_state *state = fe->demodulator_priv; | 699 | struct cx24123_state *state = fe->demodulator_priv; |
769 | int i, val; | 700 | int i, val, tone; |
770 | 701 | ||
771 | dprintk("%s:\n",__FUNCTION__); | 702 | dprintk("%s:\n",__FUNCTION__); |
772 | 703 | ||
773 | /* check if continuous tone has been stopped */ | 704 | /* stop continuous tone if enabled */ |
774 | if (state->config->use_isl6421) | 705 | tone = cx24123_readreg(state, 0x29); |
775 | val = cx24123_readlnbreg(state, 0x00) & 0x10; | 706 | if (tone & 0x10) |
776 | else | 707 | cx24123_writereg(state, 0x29, tone & ~0x50); |
777 | val = cx24123_readreg(state, 0x29) & 0x10; | ||
778 | |||
779 | |||
780 | if (val) { | ||
781 | printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); | ||
782 | return -ENOTSUPP; | ||
783 | } | ||
784 | 708 | ||
785 | /* wait for diseqc queue ready */ | 709 | /* wait for diseqc queue ready */ |
786 | cx24123_wait_for_diseqc(state); | 710 | cx24123_wait_for_diseqc(state); |
787 | 711 | ||
788 | /* select tone mode */ | 712 | /* select tone mode */ |
789 | cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); | 713 | cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb); |
790 | 714 | ||
791 | for (i = 0; i < cmd->msg_len; i++) | 715 | for (i = 0; i < cmd->msg_len; i++) |
792 | cx24123_writereg(state, 0x2C + i, cmd->msg[i]); | 716 | cx24123_writereg(state, 0x2C + i, cmd->msg[i]); |
@@ -797,36 +721,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma | |||
797 | /* wait for diseqc message to finish sending */ | 721 | /* wait for diseqc message to finish sending */ |
798 | cx24123_wait_for_diseqc(state); | 722 | cx24123_wait_for_diseqc(state); |
799 | 723 | ||
724 | /* restart continuous tone if enabled */ | ||
725 | if (tone & 0x10) { | ||
726 | cx24123_writereg(state, 0x29, tone & ~0x40); | ||
727 | } | ||
728 | |||
800 | return 0; | 729 | return 0; |
801 | } | 730 | } |
802 | 731 | ||
803 | static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) | 732 | static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) |
804 | { | 733 | { |
805 | struct cx24123_state *state = fe->demodulator_priv; | 734 | struct cx24123_state *state = fe->demodulator_priv; |
806 | int val; | 735 | int val, tone; |
807 | 736 | ||
808 | dprintk("%s:\n", __FUNCTION__); | 737 | dprintk("%s:\n", __FUNCTION__); |
809 | 738 | ||
810 | /* check if continuous tone has been stoped */ | 739 | /* stop continuous tone if enabled */ |
811 | if (state->config->use_isl6421) | 740 | tone = cx24123_readreg(state, 0x29); |
812 | val = cx24123_readlnbreg(state, 0x00) & 0x10; | 741 | if (tone & 0x10) |
813 | else | 742 | cx24123_writereg(state, 0x29, tone & ~0x50); |
814 | val = cx24123_readreg(state, 0x29) & 0x10; | ||
815 | |||
816 | |||
817 | if (val) { | ||
818 | printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); | ||
819 | return -ENOTSUPP; | ||
820 | } | ||
821 | 743 | ||
744 | /* wait for diseqc queue ready */ | ||
822 | cx24123_wait_for_diseqc(state); | 745 | cx24123_wait_for_diseqc(state); |
823 | 746 | ||
824 | /* select tone mode */ | 747 | /* select tone mode */ |
825 | val = cx24123_readreg(state, 0x2a) & 0xf8; | 748 | cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4); |
826 | cx24123_writereg(state, 0x2a, val | 0x04); | 749 | msleep(30); |
827 | |||
828 | val = cx24123_readreg(state, 0x29); | 750 | val = cx24123_readreg(state, 0x29); |
829 | |||
830 | if (burst == SEC_MINI_A) | 751 | if (burst == SEC_MINI_A) |
831 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); | 752 | cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); |
832 | else if (burst == SEC_MINI_B) | 753 | else if (burst == SEC_MINI_B) |
@@ -835,7 +756,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t | |||
835 | return -EINVAL; | 756 | return -EINVAL; |
836 | 757 | ||
837 | cx24123_wait_for_diseqc(state); | 758 | cx24123_wait_for_diseqc(state); |
759 | cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb); | ||
838 | 760 | ||
761 | /* restart continuous tone if enabled */ | ||
762 | if (tone & 0x10) { | ||
763 | cx24123_writereg(state, 0x29, tone & ~0x40); | ||
764 | } | ||
839 | return 0; | 765 | return 0; |
840 | } | 766 | } |
841 | 767 | ||
@@ -976,38 +902,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | |||
976 | struct cx24123_state *state = fe->demodulator_priv; | 902 | struct cx24123_state *state = fe->demodulator_priv; |
977 | u8 val; | 903 | u8 val; |
978 | 904 | ||
979 | switch (state->config->use_isl6421) { | 905 | /* wait for diseqc queue ready */ |
980 | case 1: | 906 | cx24123_wait_for_diseqc(state); |
981 | |||
982 | val = cx24123_readlnbreg(state, 0x0); | ||
983 | |||
984 | switch (tone) { | ||
985 | case SEC_TONE_ON: | ||
986 | dprintk("%s: isl6421 sec tone on\n",__FUNCTION__); | ||
987 | return cx24123_writelnbreg(state, 0x0, val | 0x10); | ||
988 | case SEC_TONE_OFF: | ||
989 | dprintk("%s: isl6421 sec tone off\n",__FUNCTION__); | ||
990 | return cx24123_writelnbreg(state, 0x0, val & 0x2f); | ||
991 | default: | ||
992 | printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); | ||
993 | return -EINVAL; | ||
994 | } | ||
995 | |||
996 | case 0: | ||
997 | 907 | ||
998 | val = cx24123_readreg(state, 0x29); | 908 | val = cx24123_readreg(state, 0x29) & ~0x40; |
999 | 909 | ||
1000 | switch (tone) { | 910 | switch (tone) { |
1001 | case SEC_TONE_ON: | 911 | case SEC_TONE_ON: |
1002 | dprintk("%s: setting tone on\n", __FUNCTION__); | 912 | dprintk("%s: setting tone on\n", __FUNCTION__); |
1003 | return cx24123_writereg(state, 0x29, val | 0x10); | 913 | return cx24123_writereg(state, 0x29, val | 0x10); |
1004 | case SEC_TONE_OFF: | 914 | case SEC_TONE_OFF: |
1005 | dprintk("%s: setting tone off\n",__FUNCTION__); | 915 | dprintk("%s: setting tone off\n",__FUNCTION__); |
1006 | return cx24123_writereg(state, 0x29, val & 0xef); | 916 | return cx24123_writereg(state, 0x29, val & 0xef); |
1007 | default: | 917 | default: |
1008 | printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); | 918 | printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); |
1009 | return -EINVAL; | 919 | return -EINVAL; |
1010 | } | ||
1011 | } | 920 | } |
1012 | 921 | ||
1013 | return 0; | 922 | return 0; |
@@ -1040,10 +949,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, | |||
1040 | /* setup the state */ | 949 | /* setup the state */ |
1041 | state->config = config; | 950 | state->config = config; |
1042 | state->i2c = i2c; | 951 | state->i2c = i2c; |
1043 | memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops)); | ||
1044 | state->lastber = 0; | 952 | state->lastber = 0; |
1045 | state->snr = 0; | 953 | state->snr = 0; |
1046 | state->lnbreg = 0; | ||
1047 | state->VCAarg = 0; | 954 | state->VCAarg = 0; |
1048 | state->VGAarg = 0; | 955 | state->VGAarg = 0; |
1049 | state->bandselectarg = 0; | 956 | state->bandselectarg = 0; |
@@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, | |||
1059 | } | 966 | } |
1060 | 967 | ||
1061 | /* create dvb_frontend */ | 968 | /* create dvb_frontend */ |
1062 | state->frontend.ops = &state->ops; | 969 | memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops)); |
1063 | state->frontend.demodulator_priv = state; | 970 | state->frontend.demodulator_priv = state; |
1064 | return &state->frontend; | 971 | return &state->frontend; |
1065 | 972 | ||