diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-i2c.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-i2c.c | 314 |
1 files changed, 67 insertions, 247 deletions
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 41dbbe9621a1..ca1d9557945e 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -90,26 +90,6 @@ | |||
90 | #define IVTV_M52790_I2C_ADDR 0x48 | 90 | #define IVTV_M52790_I2C_ADDR 0x48 |
91 | 91 | ||
92 | /* This array should match the IVTV_HW_ defines */ | 92 | /* This array should match the IVTV_HW_ defines */ |
93 | static const u8 hw_driverids[] = { | ||
94 | I2C_DRIVERID_CX25840, | ||
95 | I2C_DRIVERID_SAA711X, | ||
96 | I2C_DRIVERID_SAA7127, | ||
97 | I2C_DRIVERID_MSP3400, | ||
98 | I2C_DRIVERID_TUNER, | ||
99 | I2C_DRIVERID_WM8775, | ||
100 | I2C_DRIVERID_CS53L32A, | ||
101 | I2C_DRIVERID_TVEEPROM, | ||
102 | I2C_DRIVERID_SAA711X, | ||
103 | I2C_DRIVERID_UPD64031A, | ||
104 | I2C_DRIVERID_UPD64083, | ||
105 | I2C_DRIVERID_SAA717X, | ||
106 | I2C_DRIVERID_WM8739, | ||
107 | I2C_DRIVERID_VP27SMPX, | ||
108 | I2C_DRIVERID_M52790, | ||
109 | 0 /* IVTV_HW_GPIO dummy driver ID */ | ||
110 | }; | ||
111 | |||
112 | /* This array should match the IVTV_HW_ defines */ | ||
113 | static const u8 hw_addrs[] = { | 93 | static const u8 hw_addrs[] = { |
114 | IVTV_CX25840_I2C_ADDR, | 94 | IVTV_CX25840_I2C_ADDR, |
115 | IVTV_SAA7115_I2C_ADDR, | 95 | IVTV_SAA7115_I2C_ADDR, |
@@ -130,6 +110,26 @@ static const u8 hw_addrs[] = { | |||
130 | }; | 110 | }; |
131 | 111 | ||
132 | /* This array should match the IVTV_HW_ defines */ | 112 | /* This array should match the IVTV_HW_ defines */ |
113 | static const char *hw_modules[] = { | ||
114 | "cx25840", | ||
115 | "saa7115", | ||
116 | "saa7127", | ||
117 | "msp3400", | ||
118 | "tuner", | ||
119 | "wm8775", | ||
120 | "cs53l32a", | ||
121 | NULL, | ||
122 | "saa7115", | ||
123 | "upd64031a", | ||
124 | "upd64083", | ||
125 | "saa717x", | ||
126 | "wm8739", | ||
127 | "vp27smpx", | ||
128 | "m52790", | ||
129 | NULL | ||
130 | }; | ||
131 | |||
132 | /* This array should match the IVTV_HW_ defines */ | ||
133 | static const char * const hw_devicenames[] = { | 133 | static const char * const hw_devicenames[] = { |
134 | "cx25840", | 134 | "cx25840", |
135 | "saa7115", | 135 | "saa7115", |
@@ -151,80 +151,58 @@ static const char * const hw_devicenames[] = { | |||
151 | 151 | ||
152 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) | 152 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx) |
153 | { | 153 | { |
154 | struct i2c_board_info info; | 154 | struct v4l2_subdev *sd; |
155 | struct i2c_client *c; | 155 | struct i2c_adapter *adap = &itv->i2c_adap; |
156 | u8 id; | 156 | const char *mod = hw_modules[idx]; |
157 | int i; | 157 | const char *type = hw_devicenames[idx]; |
158 | u32 hw = 1 << idx; | ||
158 | 159 | ||
159 | IVTV_DEBUG_I2C("i2c client register\n"); | 160 | if (idx >= ARRAY_SIZE(hw_addrs)) |
160 | if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0) | ||
161 | return -1; | 161 | return -1; |
162 | id = hw_driverids[idx]; | 162 | if (hw == IVTV_HW_TUNER) { |
163 | memset(&info, 0, sizeof(info)); | 163 | /* special tuner handling */ |
164 | strlcpy(info.type, hw_devicenames[idx], sizeof(info.type)); | 164 | sd = v4l2_i2c_new_probed_subdev(adap, mod, type, |
165 | info.addr = hw_addrs[idx]; | 165 | itv->card_i2c->radio); |
166 | for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {} | 166 | if (sd) |
167 | 167 | sd->grp_id = 1 << idx; | |
168 | if (i == I2C_CLIENTS_MAX) { | 168 | sd = v4l2_i2c_new_probed_subdev(adap, mod, type, |
169 | IVTV_ERR("insufficient room for new I2C client!\n"); | 169 | itv->card_i2c->demod); |
170 | return -ENOMEM; | 170 | if (sd) |
171 | sd->grp_id = 1 << idx; | ||
172 | sd = v4l2_i2c_new_probed_subdev(adap, mod, type, | ||
173 | itv->card_i2c->tv); | ||
174 | if (sd) | ||
175 | sd->grp_id = 1 << idx; | ||
176 | return sd ? 0 : -1; | ||
171 | } | 177 | } |
178 | if (!hw_addrs[idx]) | ||
179 | return -1; | ||
180 | if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { | ||
181 | unsigned short addrs[2] = { hw_addrs[idx], I2C_CLIENT_END }; | ||
172 | 182 | ||
173 | if (id != I2C_DRIVERID_TUNER) { | 183 | sd = v4l2_i2c_new_probed_subdev(adap, mod, type, addrs); |
174 | if (id == I2C_DRIVERID_UPD64031A || | 184 | } else { |
175 | id == I2C_DRIVERID_UPD64083) { | 185 | sd = v4l2_i2c_new_subdev(adap, mod, type, hw_addrs[idx]); |
176 | unsigned short addrs[2] = { info.addr, I2C_CLIENT_END }; | ||
177 | |||
178 | c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs); | ||
179 | } else | ||
180 | c = i2c_new_device(&itv->i2c_adap, &info); | ||
181 | if (c && c->driver == NULL) | ||
182 | i2c_unregister_device(c); | ||
183 | else if (c) | ||
184 | itv->i2c_clients[i] = c; | ||
185 | return itv->i2c_clients[i] ? 0 : -ENODEV; | ||
186 | } | 186 | } |
187 | 187 | if (sd) | |
188 | /* special tuner handling */ | 188 | sd->grp_id = 1 << idx; |
189 | c = i2c_new_probed_device(&itv->i2c_adap, &info, itv->card_i2c->radio); | 189 | return sd ? 0 : -1; |
190 | if (c && c->driver == NULL) | ||
191 | i2c_unregister_device(c); | ||
192 | else if (c) | ||
193 | itv->i2c_clients[i++] = c; | ||
194 | c = i2c_new_probed_device(&itv->i2c_adap, &info, itv->card_i2c->demod); | ||
195 | if (c && c->driver == NULL) | ||
196 | i2c_unregister_device(c); | ||
197 | else if (c) | ||
198 | itv->i2c_clients[i++] = c; | ||
199 | c = i2c_new_probed_device(&itv->i2c_adap, &info, itv->card_i2c->tv); | ||
200 | if (c && c->driver == NULL) | ||
201 | i2c_unregister_device(c); | ||
202 | else if (c) | ||
203 | itv->i2c_clients[i++] = c; | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int attach_inform(struct i2c_client *client) | ||
208 | { | ||
209 | return 0; | ||
210 | } | 190 | } |
211 | 191 | ||
212 | static int detach_inform(struct i2c_client *client) | 192 | struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw) |
213 | { | 193 | { |
214 | int i; | 194 | struct v4l2_subdev *result = NULL; |
215 | struct ivtv *itv = (struct ivtv *)i2c_get_adapdata(client->adapter); | 195 | struct v4l2_subdev *sd; |
216 | 196 | ||
217 | IVTV_DEBUG_I2C("i2c client detach\n"); | 197 | spin_lock(&itv->device.lock); |
218 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | 198 | v4l2_device_for_each_subdev(sd, &itv->device) { |
219 | if (itv->i2c_clients[i] == client) { | 199 | if (sd->grp_id == hw) { |
220 | itv->i2c_clients[i] = NULL; | 200 | result = sd; |
221 | break; | 201 | break; |
222 | } | 202 | } |
223 | } | 203 | } |
224 | IVTV_DEBUG_I2C("i2c detach [client=%s,%s]\n", | 204 | spin_unlock(&itv->device.lock); |
225 | client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); | 205 | return result; |
226 | |||
227 | return 0; | ||
228 | } | 206 | } |
229 | 207 | ||
230 | /* Set the serial clock line to the desired state */ | 208 | /* Set the serial clock line to the desired state */ |
@@ -494,7 +472,8 @@ static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, | |||
494 | intervening stop condition */ | 472 | intervening stop condition */ |
495 | static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | 473 | static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) |
496 | { | 474 | { |
497 | struct ivtv *itv = i2c_get_adapdata(i2c_adap); | 475 | struct v4l2_device *drv = i2c_get_adapdata(i2c_adap); |
476 | struct ivtv *itv = to_ivtv(drv); | ||
498 | int retval; | 477 | int retval; |
499 | int i; | 478 | int i; |
500 | 479 | ||
@@ -530,8 +509,6 @@ static struct i2c_adapter ivtv_i2c_adap_hw_template = { | |||
530 | .id = I2C_HW_B_CX2341X, | 509 | .id = I2C_HW_B_CX2341X, |
531 | .algo = &ivtv_algo, | 510 | .algo = &ivtv_algo, |
532 | .algo_data = NULL, /* filled from template */ | 511 | .algo_data = NULL, /* filled from template */ |
533 | .client_register = attach_inform, | ||
534 | .client_unregister = detach_inform, | ||
535 | .owner = THIS_MODULE, | 512 | .owner = THIS_MODULE, |
536 | }; | 513 | }; |
537 | 514 | ||
@@ -583,8 +560,6 @@ static struct i2c_adapter ivtv_i2c_adap_template = { | |||
583 | .id = I2C_HW_B_CX2341X, | 560 | .id = I2C_HW_B_CX2341X, |
584 | .algo = NULL, /* set by i2c-algo-bit */ | 561 | .algo = NULL, /* set by i2c-algo-bit */ |
585 | .algo_data = NULL, /* filled from template */ | 562 | .algo_data = NULL, /* filled from template */ |
586 | .client_register = attach_inform, | ||
587 | .client_unregister = detach_inform, | ||
588 | .owner = THIS_MODULE, | 563 | .owner = THIS_MODULE, |
589 | }; | 564 | }; |
590 | 565 | ||
@@ -601,160 +576,6 @@ static struct i2c_client ivtv_i2c_client_template = { | |||
601 | .name = "ivtv internal", | 576 | .name = "ivtv internal", |
602 | }; | 577 | }; |
603 | 578 | ||
604 | int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg) | ||
605 | { | ||
606 | struct i2c_client *client; | ||
607 | int retval; | ||
608 | int i; | ||
609 | |||
610 | IVTV_DEBUG_I2C("call_i2c_client addr=%02x\n", addr); | ||
611 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | ||
612 | client = itv->i2c_clients[i]; | ||
613 | if (client == NULL || client->driver == NULL || | ||
614 | client->driver->command == NULL) | ||
615 | continue; | ||
616 | if (addr == client->addr) { | ||
617 | retval = client->driver->command(client, cmd, arg); | ||
618 | return retval; | ||
619 | } | ||
620 | } | ||
621 | if (cmd != VIDIOC_G_CHIP_IDENT) | ||
622 | IVTV_ERR("i2c addr 0x%02x not found for command 0x%x\n", addr, cmd); | ||
623 | return -ENODEV; | ||
624 | } | ||
625 | |||
626 | /* Find the i2c device based on the driver ID and return | ||
627 | its i2c address or -ENODEV if no matching device was found. */ | ||
628 | static int ivtv_i2c_id_addr(struct ivtv *itv, u32 id) | ||
629 | { | ||
630 | struct i2c_client *client; | ||
631 | int retval = -ENODEV; | ||
632 | int i; | ||
633 | |||
634 | for (i = 0; i < I2C_CLIENTS_MAX; i++) { | ||
635 | client = itv->i2c_clients[i]; | ||
636 | if (client == NULL || client->driver == NULL) | ||
637 | continue; | ||
638 | if (id == client->driver->id) { | ||
639 | retval = client->addr; | ||
640 | break; | ||
641 | } | ||
642 | } | ||
643 | return retval; | ||
644 | } | ||
645 | |||
646 | /* Find the i2c device name matching the DRIVERID */ | ||
647 | static const char *ivtv_i2c_id_name(u32 id) | ||
648 | { | ||
649 | int i; | ||
650 | |||
651 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | ||
652 | if (hw_driverids[i] == id) | ||
653 | return hw_devicenames[i]; | ||
654 | return "unknown device"; | ||
655 | } | ||
656 | |||
657 | /* Find the i2c device name matching the IVTV_HW_ flag */ | ||
658 | static const char *ivtv_i2c_hw_name(u32 hw) | ||
659 | { | ||
660 | int i; | ||
661 | |||
662 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | ||
663 | if (1 << i == hw) | ||
664 | return hw_devicenames[i]; | ||
665 | return "unknown device"; | ||
666 | } | ||
667 | |||
668 | /* Find the i2c device matching the IVTV_HW_ flag and return | ||
669 | its i2c address or -ENODEV if no matching device was found. */ | ||
670 | int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw) | ||
671 | { | ||
672 | int i; | ||
673 | |||
674 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | ||
675 | if (1 << i == hw) | ||
676 | return ivtv_i2c_id_addr(itv, hw_driverids[i]); | ||
677 | return -ENODEV; | ||
678 | } | ||
679 | |||
680 | /* Calls i2c device based on IVTV_HW_ flag. If hw == 0, then do nothing. | ||
681 | If hw == IVTV_HW_GPIO then call the gpio handler. */ | ||
682 | int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg) | ||
683 | { | ||
684 | int addr; | ||
685 | |||
686 | if (hw == IVTV_HW_GPIO) | ||
687 | return ivtv_gpio(itv, cmd, arg); | ||
688 | if (hw == 0) | ||
689 | return 0; | ||
690 | |||
691 | addr = ivtv_i2c_hw_addr(itv, hw); | ||
692 | if (addr < 0) { | ||
693 | IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x\n", | ||
694 | hw, ivtv_i2c_hw_name(hw), cmd); | ||
695 | return addr; | ||
696 | } | ||
697 | return ivtv_call_i2c_client(itv, addr, cmd, arg); | ||
698 | } | ||
699 | |||
700 | /* Calls i2c device based on I2C driver ID. */ | ||
701 | int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg) | ||
702 | { | ||
703 | int addr; | ||
704 | |||
705 | addr = ivtv_i2c_id_addr(itv, id); | ||
706 | if (addr < 0) { | ||
707 | if (cmd != VIDIOC_G_CHIP_IDENT) | ||
708 | IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x\n", | ||
709 | id, ivtv_i2c_id_name(id), cmd); | ||
710 | return addr; | ||
711 | } | ||
712 | return ivtv_call_i2c_client(itv, addr, cmd, arg); | ||
713 | } | ||
714 | |||
715 | int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg) | ||
716 | { | ||
717 | return ivtv_call_i2c_client(itv, IVTV_CX25840_I2C_ADDR, cmd, arg); | ||
718 | } | ||
719 | |||
720 | int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg) | ||
721 | { | ||
722 | return ivtv_call_i2c_client(itv, IVTV_SAA7115_I2C_ADDR, cmd, arg); | ||
723 | } | ||
724 | |||
725 | int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg) | ||
726 | { | ||
727 | return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg); | ||
728 | } | ||
729 | EXPORT_SYMBOL(ivtv_saa7127); | ||
730 | |||
731 | int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg) | ||
732 | { | ||
733 | return ivtv_call_i2c_client(itv, IVTV_SAA717x_I2C_ADDR, cmd, arg); | ||
734 | } | ||
735 | |||
736 | int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg) | ||
737 | { | ||
738 | return ivtv_call_i2c_client(itv, IVTV_UPD64031A_I2C_ADDR, cmd, arg); | ||
739 | } | ||
740 | |||
741 | int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg) | ||
742 | { | ||
743 | return ivtv_call_i2c_client(itv, IVTV_UPD64083_I2C_ADDR, cmd, arg); | ||
744 | } | ||
745 | |||
746 | /* broadcast cmd for all I2C clients and for the gpio subsystem */ | ||
747 | void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg) | ||
748 | { | ||
749 | if (itv->i2c_adap.algo == NULL) { | ||
750 | IVTV_ERR("Adapter is not set"); | ||
751 | return; | ||
752 | } | ||
753 | i2c_clients_command(&itv->i2c_adap, cmd, arg); | ||
754 | if (itv->hw_flags & IVTV_HW_GPIO) | ||
755 | ivtv_gpio(itv, cmd, arg); | ||
756 | } | ||
757 | |||
758 | /* init + register i2c algo-bit adapter */ | 579 | /* init + register i2c algo-bit adapter */ |
759 | int init_ivtv_i2c(struct ivtv *itv) | 580 | int init_ivtv_i2c(struct ivtv *itv) |
760 | { | 581 | { |
@@ -763,10 +584,9 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
763 | /* Sanity checks for the I2C hardware arrays. They must be the | 584 | /* Sanity checks for the I2C hardware arrays. They must be the |
764 | * same size and GPIO must be the last entry. | 585 | * same size and GPIO must be the last entry. |
765 | */ | 586 | */ |
766 | if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) || | 587 | if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || |
767 | ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || | 588 | ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_modules) || |
768 | IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1)) || | 589 | IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1))) { |
769 | hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) { | ||
770 | IVTV_ERR("Mismatched I2C hardware arrays\n"); | 590 | IVTV_ERR("Mismatched I2C hardware arrays\n"); |
771 | return -ENODEV; | 591 | return -ENODEV; |
772 | } | 592 | } |
@@ -783,8 +603,8 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
783 | itv->i2c_adap.algo_data = &itv->i2c_algo; | 603 | itv->i2c_adap.algo_data = &itv->i2c_algo; |
784 | 604 | ||
785 | sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", | 605 | sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", |
786 | itv->num); | 606 | itv->instance); |
787 | i2c_set_adapdata(&itv->i2c_adap, itv); | 607 | i2c_set_adapdata(&itv->i2c_adap, &itv->device); |
788 | 608 | ||
789 | memcpy(&itv->i2c_client, &ivtv_i2c_client_template, | 609 | memcpy(&itv->i2c_client, &ivtv_i2c_client_template, |
790 | sizeof(struct i2c_client)); | 610 | sizeof(struct i2c_client)); |