diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/control.c | 64 | ||||
-rw-r--r-- | sound/i2c/other/Makefile | 2 | ||||
-rw-r--r-- | sound/i2c/other/tea575x-tuner.c | 52 | ||||
-rw-r--r-- | sound/pci/Kconfig | 14 | ||||
-rw-r--r-- | sound/pci/es1968.c | 125 | ||||
-rw-r--r-- | sound/pci/fm801.c | 1 |
6 files changed, 239 insertions, 19 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index a08ad57c49b6..5d98194bcad5 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -366,6 +366,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
366 | EXPORT_SYMBOL(snd_ctl_add); | 366 | EXPORT_SYMBOL(snd_ctl_add); |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * snd_ctl_replace - replace the control instance of the card | ||
370 | * @card: the card instance | ||
371 | * @kcontrol: the control instance to replace | ||
372 | * @add_on_replace: add the control if not already added | ||
373 | * | ||
374 | * Replaces the given control. If the given control does not exist | ||
375 | * and the add_on_replace flag is set, the control is added. If the | ||
376 | * control exists, it is destroyed first. | ||
377 | * | ||
378 | * Returns zero if successful, or a negative error code on failure. | ||
379 | * | ||
380 | * It frees automatically the control which cannot be added or replaced. | ||
381 | */ | ||
382 | int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, | ||
383 | bool add_on_replace) | ||
384 | { | ||
385 | struct snd_ctl_elem_id id; | ||
386 | unsigned int idx; | ||
387 | struct snd_kcontrol *old; | ||
388 | int ret; | ||
389 | |||
390 | if (!kcontrol) | ||
391 | return -EINVAL; | ||
392 | if (snd_BUG_ON(!card || !kcontrol->info)) { | ||
393 | ret = -EINVAL; | ||
394 | goto error; | ||
395 | } | ||
396 | id = kcontrol->id; | ||
397 | down_write(&card->controls_rwsem); | ||
398 | old = snd_ctl_find_id(card, &id); | ||
399 | if (!old) { | ||
400 | if (add_on_replace) | ||
401 | goto add; | ||
402 | up_write(&card->controls_rwsem); | ||
403 | ret = -EINVAL; | ||
404 | goto error; | ||
405 | } | ||
406 | ret = snd_ctl_remove(card, old); | ||
407 | if (ret < 0) { | ||
408 | up_write(&card->controls_rwsem); | ||
409 | goto error; | ||
410 | } | ||
411 | add: | ||
412 | if (snd_ctl_find_hole(card, kcontrol->count) < 0) { | ||
413 | up_write(&card->controls_rwsem); | ||
414 | ret = -ENOMEM; | ||
415 | goto error; | ||
416 | } | ||
417 | list_add_tail(&kcontrol->list, &card->controls); | ||
418 | card->controls_count += kcontrol->count; | ||
419 | kcontrol->id.numid = card->last_numid + 1; | ||
420 | card->last_numid += kcontrol->count; | ||
421 | up_write(&card->controls_rwsem); | ||
422 | for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) | ||
423 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); | ||
424 | return 0; | ||
425 | |||
426 | error: | ||
427 | snd_ctl_free_one(kcontrol); | ||
428 | return ret; | ||
429 | } | ||
430 | EXPORT_SYMBOL(snd_ctl_replace); | ||
431 | |||
432 | /** | ||
369 | * snd_ctl_remove - remove the control from the card and release it | 433 | * snd_ctl_remove - remove the control from the card and release it |
370 | * @card: the card instance | 434 | * @card: the card instance |
371 | * @kcontrol: the control instance to remove | 435 | * @kcontrol: the control instance to remove |
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index 2dad40f3f622..c95d8f1aae87 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o | |||
14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 14 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 15 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o | 16 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o |
17 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o | 17 | obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o |
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index ee538f1ae846..9f35f378a17d 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c | |||
@@ -37,8 +37,8 @@ static int radio_nr = -1; | |||
37 | module_param(radio_nr, int, 0); | 37 | module_param(radio_nr, int, 0); |
38 | 38 | ||
39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | 39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) |
40 | #define FREQ_LO (87 * 16000) | 40 | #define FREQ_LO (50UL * 16000) |
41 | #define FREQ_HI (108 * 16000) | 41 | #define FREQ_HI (150UL * 16000) |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * definitions | 44 | * definitions |
@@ -77,15 +77,29 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
77 | * lowlevel part | 77 | * lowlevel part |
78 | */ | 78 | */ |
79 | 79 | ||
80 | static void snd_tea575x_get_freq(struct snd_tea575x *tea) | ||
81 | { | ||
82 | unsigned long freq; | ||
83 | |||
84 | freq = tea->ops->read(tea) & TEA575X_BIT_FREQ_MASK; | ||
85 | /* freq *= 12.5 */ | ||
86 | freq *= 125; | ||
87 | freq /= 10; | ||
88 | /* crystal fixup */ | ||
89 | if (tea->tea5759) | ||
90 | freq += tea->freq_fixup; | ||
91 | else | ||
92 | freq -= tea->freq_fixup; | ||
93 | |||
94 | tea->freq = freq * 16; /* from kHz */ | ||
95 | } | ||
96 | |||
80 | static void snd_tea575x_set_freq(struct snd_tea575x *tea) | 97 | static void snd_tea575x_set_freq(struct snd_tea575x *tea) |
81 | { | 98 | { |
82 | unsigned long freq; | 99 | unsigned long freq; |
83 | 100 | ||
84 | freq = tea->freq / 16; /* to kHz */ | 101 | freq = clamp(tea->freq, FREQ_LO, FREQ_HI); |
85 | if (freq > 108000) | 102 | freq /= 16; /* to kHz */ |
86 | freq = 108000; | ||
87 | if (freq < 87000) | ||
88 | freq = 87000; | ||
89 | /* crystal fixup */ | 103 | /* crystal fixup */ |
90 | if (tea->tea5759) | 104 | if (tea->tea5759) |
91 | freq -= tea->freq_fixup; | 105 | freq -= tea->freq_fixup; |
@@ -109,29 +123,33 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
109 | { | 123 | { |
110 | struct snd_tea575x *tea = video_drvdata(file); | 124 | struct snd_tea575x *tea = video_drvdata(file); |
111 | 125 | ||
112 | strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757"); | ||
113 | strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); | 126 | strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); |
114 | strlcpy(v->card, "Maestro Radio", sizeof(v->card)); | 127 | strlcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757", sizeof(v->card)); |
115 | sprintf(v->bus_info, "PCI"); | 128 | sprintf(v->bus_info, "PCI"); |
116 | v->version = RADIO_VERSION; | 129 | v->version = RADIO_VERSION; |
117 | v->capabilities = V4L2_CAP_TUNER; | 130 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
118 | return 0; | 131 | return 0; |
119 | } | 132 | } |
120 | 133 | ||
121 | static int vidioc_g_tuner(struct file *file, void *priv, | 134 | static int vidioc_g_tuner(struct file *file, void *priv, |
122 | struct v4l2_tuner *v) | 135 | struct v4l2_tuner *v) |
123 | { | 136 | { |
137 | struct snd_tea575x *tea = video_drvdata(file); | ||
138 | |||
124 | if (v->index > 0) | 139 | if (v->index > 0) |
125 | return -EINVAL; | 140 | return -EINVAL; |
126 | 141 | ||
142 | tea->ops->read(tea); | ||
143 | |||
127 | strcpy(v->name, "FM"); | 144 | strcpy(v->name, "FM"); |
128 | v->type = V4L2_TUNER_RADIO; | 145 | v->type = V4L2_TUNER_RADIO; |
146 | v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | ||
129 | v->rangelow = FREQ_LO; | 147 | v->rangelow = FREQ_LO; |
130 | v->rangehigh = FREQ_HI; | 148 | v->rangehigh = FREQ_HI; |
131 | v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | 149 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
132 | v->capability = V4L2_TUNER_CAP_LOW; | 150 | v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; |
133 | v->audmode = V4L2_TUNER_MODE_MONO; | 151 | v->signal = tea->tuned ? 0xffff : 0; |
134 | v->signal = 0xffff; | 152 | |
135 | return 0; | 153 | return 0; |
136 | } | 154 | } |
137 | 155 | ||
@@ -148,7 +166,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
148 | { | 166 | { |
149 | struct snd_tea575x *tea = video_drvdata(file); | 167 | struct snd_tea575x *tea = video_drvdata(file); |
150 | 168 | ||
169 | if (f->tuner != 0) | ||
170 | return -EINVAL; | ||
151 | f->type = V4L2_TUNER_RADIO; | 171 | f->type = V4L2_TUNER_RADIO; |
172 | snd_tea575x_get_freq(tea); | ||
152 | f->frequency = tea->freq; | 173 | f->frequency = tea->freq; |
153 | return 0; | 174 | return 0; |
154 | } | 175 | } |
@@ -158,6 +179,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
158 | { | 179 | { |
159 | struct snd_tea575x *tea = video_drvdata(file); | 180 | struct snd_tea575x *tea = video_drvdata(file); |
160 | 181 | ||
182 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
183 | return -EINVAL; | ||
184 | |||
161 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) | 185 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) |
162 | return -EINVAL; | 186 | return -EINVAL; |
163 | 187 | ||
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 389cd7931668..f9f533fccccf 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -534,6 +534,14 @@ config SND_ES1968_INPUT | |||
534 | If you say N the buttons will directly control the master volume. | 534 | If you say N the buttons will directly control the master volume. |
535 | It is recommended to say Y. | 535 | It is recommended to say Y. |
536 | 536 | ||
537 | config SND_ES1968_RADIO | ||
538 | bool "Enable TEA5757 radio tuner support for es1968" | ||
539 | depends on SND_ES1968 | ||
540 | depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 | ||
541 | help | ||
542 | Say Y here to include support for TEA5757 radio tuner integrated on | ||
543 | some MediaForte cards (e.g. SF64-PCE2). | ||
544 | |||
537 | config SND_FM801 | 545 | config SND_FM801 |
538 | tristate "ForteMedia FM801" | 546 | tristate "ForteMedia FM801" |
539 | select SND_OPL3_LIB | 547 | select SND_OPL3_LIB |
@@ -555,10 +563,10 @@ config SND_FM801_TEA575X_BOOL | |||
555 | FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media | 563 | FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media |
556 | Forte SF256-PCS-02) into the snd-fm801 driver. | 564 | Forte SF256-PCS-02) into the snd-fm801 driver. |
557 | 565 | ||
558 | config SND_FM801_TEA575X | 566 | config SND_TEA575X |
559 | tristate | 567 | tristate |
560 | depends on SND_FM801_TEA575X_BOOL | 568 | depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO |
561 | default SND_FM801 | 569 | default SND_FM801 || SND_ES1968 |
562 | 570 | ||
563 | source "sound/pci/hda/Kconfig" | 571 | source "sound/pci/hda/Kconfig" |
564 | 572 | ||
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 7c17f45d876d..faf9138970ae 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -112,6 +112,10 @@ | |||
112 | #include <sound/ac97_codec.h> | 112 | #include <sound/ac97_codec.h> |
113 | #include <sound/initval.h> | 113 | #include <sound/initval.h> |
114 | 114 | ||
115 | #ifdef CONFIG_SND_ES1968_RADIO | ||
116 | #include <sound/tea575x-tuner.h> | ||
117 | #endif | ||
118 | |||
115 | #define CARD_NAME "ESS Maestro1/2" | 119 | #define CARD_NAME "ESS Maestro1/2" |
116 | #define DRIVER_NAME "ES1968" | 120 | #define DRIVER_NAME "ES1968" |
117 | 121 | ||
@@ -553,6 +557,10 @@ struct es1968 { | |||
553 | spinlock_t ac97_lock; | 557 | spinlock_t ac97_lock; |
554 | struct tasklet_struct hwvol_tq; | 558 | struct tasklet_struct hwvol_tq; |
555 | #endif | 559 | #endif |
560 | |||
561 | #ifdef CONFIG_SND_ES1968_RADIO | ||
562 | struct snd_tea575x tea; | ||
563 | #endif | ||
556 | }; | 564 | }; |
557 | 565 | ||
558 | static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); | 566 | static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); |
@@ -2571,6 +2579,111 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip) | |||
2571 | } | 2579 | } |
2572 | #endif /* CONFIG_SND_ES1968_INPUT */ | 2580 | #endif /* CONFIG_SND_ES1968_INPUT */ |
2573 | 2581 | ||
2582 | #ifdef CONFIG_SND_ES1968_RADIO | ||
2583 | #define GPIO_DATA 0x60 | ||
2584 | #define IO_MASK 4 /* mask register offset from GPIO_DATA | ||
2585 | bits 1=unmask write to given bit */ | ||
2586 | #define IO_DIR 8 /* direction register offset from GPIO_DATA | ||
2587 | bits 0/1=read/write direction */ | ||
2588 | /* mask bits for GPIO lines */ | ||
2589 | #define STR_DATA 0x0040 /* GPIO6 */ | ||
2590 | #define STR_CLK 0x0080 /* GPIO7 */ | ||
2591 | #define STR_WREN 0x0100 /* GPIO8 */ | ||
2592 | #define STR_MOST 0x0200 /* GPIO9 */ | ||
2593 | |||
2594 | static void snd_es1968_tea575x_write(struct snd_tea575x *tea, unsigned int val) | ||
2595 | { | ||
2596 | struct es1968 *chip = tea->private_data; | ||
2597 | unsigned long io = chip->io_port + GPIO_DATA; | ||
2598 | u16 l, bits; | ||
2599 | u16 omask, odir; | ||
2600 | |||
2601 | omask = inw(io + IO_MASK); | ||
2602 | odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); | ||
2603 | outw(odir | STR_DATA, io + IO_DIR); | ||
2604 | outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); | ||
2605 | udelay(16); | ||
2606 | |||
2607 | for (l = 25; l; l--) { | ||
2608 | bits = ((val >> 18) & STR_DATA) | STR_WREN; | ||
2609 | val <<= 1; /* shift data */ | ||
2610 | outw(bits, io); /* start strobe */ | ||
2611 | udelay(2); | ||
2612 | outw(bits | STR_CLK, io); /* HI level */ | ||
2613 | udelay(2); | ||
2614 | outw(bits, io); /* LO level */ | ||
2615 | udelay(4); | ||
2616 | } | ||
2617 | |||
2618 | if (!tea->mute) | ||
2619 | outw(0, io); | ||
2620 | |||
2621 | udelay(4); | ||
2622 | outw(omask, io + IO_MASK); | ||
2623 | outw(odir, io + IO_DIR); | ||
2624 | msleep(125); | ||
2625 | } | ||
2626 | |||
2627 | static unsigned int snd_es1968_tea575x_read(struct snd_tea575x *tea) | ||
2628 | { | ||
2629 | struct es1968 *chip = tea->private_data; | ||
2630 | unsigned long io = chip->io_port + GPIO_DATA; | ||
2631 | u16 l, rdata; | ||
2632 | u32 data = 0; | ||
2633 | u16 omask; | ||
2634 | |||
2635 | omask = inw(io + IO_MASK); | ||
2636 | outw(~(STR_CLK | STR_WREN), io + IO_MASK); | ||
2637 | outw(0, io); | ||
2638 | udelay(16); | ||
2639 | |||
2640 | for (l = 24; l--;) { | ||
2641 | outw(STR_CLK, io); /* HI state */ | ||
2642 | udelay(2); | ||
2643 | if (!l) | ||
2644 | tea->tuned = inw(io) & STR_MOST ? 0 : 1; | ||
2645 | outw(0, io); /* LO state */ | ||
2646 | udelay(2); | ||
2647 | data <<= 1; /* shift data */ | ||
2648 | rdata = inw(io); | ||
2649 | if (!l) | ||
2650 | tea->stereo = (rdata & STR_MOST) ? 0 : 1; | ||
2651 | else if (l && rdata & STR_DATA) | ||
2652 | data++; | ||
2653 | udelay(2); | ||
2654 | } | ||
2655 | |||
2656 | if (tea->mute) | ||
2657 | outw(STR_WREN, io); | ||
2658 | |||
2659 | udelay(4); | ||
2660 | outw(omask, io + IO_MASK); | ||
2661 | |||
2662 | return data & 0x3ffe; | ||
2663 | } | ||
2664 | |||
2665 | static void snd_es1968_tea575x_mute(struct snd_tea575x *tea, unsigned int mute) | ||
2666 | { | ||
2667 | struct es1968 *chip = tea->private_data; | ||
2668 | unsigned long io = chip->io_port + GPIO_DATA; | ||
2669 | u16 omask; | ||
2670 | |||
2671 | omask = inw(io + IO_MASK); | ||
2672 | outw(~STR_WREN, io + IO_MASK); | ||
2673 | tea->mute = mute; | ||
2674 | outw(tea->mute ? STR_WREN : 0, io); | ||
2675 | udelay(4); | ||
2676 | outw(omask, io + IO_MASK); | ||
2677 | msleep(125); | ||
2678 | } | ||
2679 | |||
2680 | static struct snd_tea575x_ops snd_es1968_tea_ops = { | ||
2681 | .write = snd_es1968_tea575x_write, | ||
2682 | .read = snd_es1968_tea575x_read, | ||
2683 | .mute = snd_es1968_tea575x_mute, | ||
2684 | }; | ||
2685 | #endif | ||
2686 | |||
2574 | static int snd_es1968_free(struct es1968 *chip) | 2687 | static int snd_es1968_free(struct es1968 *chip) |
2575 | { | 2688 | { |
2576 | #ifdef CONFIG_SND_ES1968_INPUT | 2689 | #ifdef CONFIG_SND_ES1968_INPUT |
@@ -2585,6 +2698,10 @@ static int snd_es1968_free(struct es1968 *chip) | |||
2585 | outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ | 2698 | outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ |
2586 | } | 2699 | } |
2587 | 2700 | ||
2701 | #ifdef CONFIG_SND_ES1968_RADIO | ||
2702 | snd_tea575x_exit(&chip->tea); | ||
2703 | #endif | ||
2704 | |||
2588 | if (chip->irq >= 0) | 2705 | if (chip->irq >= 0) |
2589 | free_irq(chip->irq, chip); | 2706 | free_irq(chip->irq, chip); |
2590 | snd_es1968_free_gameport(chip); | 2707 | snd_es1968_free_gameport(chip); |
@@ -2723,6 +2840,14 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2723 | 2840 | ||
2724 | snd_card_set_dev(card, &pci->dev); | 2841 | snd_card_set_dev(card, &pci->dev); |
2725 | 2842 | ||
2843 | #ifdef CONFIG_SND_ES1968_RADIO | ||
2844 | chip->tea.card = card; | ||
2845 | chip->tea.freq_fixup = 10700; | ||
2846 | chip->tea.private_data = chip; | ||
2847 | chip->tea.ops = &snd_es1968_tea_ops; | ||
2848 | snd_tea575x_init(&chip->tea); | ||
2849 | #endif | ||
2850 | |||
2726 | *chip_ret = chip; | 2851 | *chip_ret = chip; |
2727 | 2852 | ||
2728 | return 0; | 2853 | return 0; |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index e1baad74ea4b..f4dc1c77202b 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1453,7 +1453,6 @@ static int __devinit snd_fm801_create(struct snd_card *card, | |||
1453 | #ifdef TEA575X_RADIO | 1453 | #ifdef TEA575X_RADIO |
1454 | if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && | 1454 | if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && |
1455 | (tea575x_tuner & TUNER_TYPE_MASK) < 4) { | 1455 | (tea575x_tuner & TUNER_TYPE_MASK) < 4) { |
1456 | chip->tea.dev_nr = tea575x_tuner >> 16; | ||
1457 | chip->tea.card = card; | 1456 | chip->tea.card = card; |
1458 | chip->tea.freq_fixup = 10700; | 1457 | chip->tea.freq_fixup = 10700; |
1459 | chip->tea.private_data = chip; | 1458 | chip->tea.private_data = chip; |