drivers/media/radio/radio-tea5777.c

Source file repositories/reference/linux-study-clean/drivers/media/radio/radio-tea5777.c

File Facts

System
Linux kernel
Corpus path
drivers/media/radio/radio-tea5777.c
Extension
.c
Size
16182 bytes
Lines
588
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (tea->freq < rangelow || tea->freq > rangehigh) {
			tea->freq = clamp(tea->freq, rangelow,
						     rangehigh);
			res = radio_tea5777_set_freq(tea);
			if (res)
				return res;
		}
	} else {
		rangelow  = bands[tea->band].rangelow;
		rangehigh = bands[tea->band].rangehigh;
	}

	spacing   = (tea->band == BAND_AM) ? (5 * 16) : (200 * 16); /* kHz */
	orig_freq = tea->freq;

	tea->write_reg |= TEA5777_W_PROGBLIM_MASK;
	if (tea->seek_rangelow != rangelow) {
		tea->write_reg &= ~TEA5777_W_UPDWN_MASK;
		tea->freq = rangelow;
		res = radio_tea5777_set_freq(tea);
		if (res)
			goto leave;
		tea->seek_rangelow = rangelow;
	}
	if (tea->seek_rangehigh != rangehigh) {
		tea->write_reg |= TEA5777_W_UPDWN_MASK;
		tea->freq = rangehigh;
		res = radio_tea5777_set_freq(tea);
		if (res)
			goto leave;
		tea->seek_rangehigh = rangehigh;
	}
	tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK;

	tea->write_reg |= TEA5777_W_SEARCH_MASK;
	if (a->seek_upward) {
		tea->write_reg |= TEA5777_W_UPDWN_MASK;
		tea->freq = orig_freq + spacing;
	} else {
		tea->write_reg &= ~TEA5777_W_UPDWN_MASK;
		tea->freq = orig_freq - spacing;
	}
	res = radio_tea5777_set_freq(tea);
	if (res)
		goto leave;

	timeout = jiffies + msecs_to_jiffies(5000);
	for (;;) {
		if (time_after(jiffies, timeout)) {
			res = -ENODATA;
			break;
		}

		res = radio_tea5777_update_read_reg(tea, 100);
		if (res)
			break;

		/*
		 * Note we use tea->freq to track how far we've searched sofar
		 * this is necessary to ensure we continue seeking at the right
		 * point, in the write_before_read case.
		 */
		tea->freq = (tea->read_reg & TEA5777_R_FM_PLL_MASK);
		tea->freq = tea5777_freq_to_v4l2_freq(tea, tea->freq);

		if ((tea->read_reg & TEA5777_R_SFOUND_MASK)) {
			tea->write_reg &= ~TEA5777_W_SEARCH_MASK;
			return 0;
		}

		if (tea->read_reg & TEA5777_R_BLIM_MASK) {
			res = -ENODATA;
			break;
		}

		/* Force read_reg update */
		tea->read_reg = -1;
	}
leave:
	tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK;
	tea->write_reg &= ~TEA5777_W_SEARCH_MASK;
	tea->freq = orig_freq;
	radio_tea5777_set_freq(tea);
	return res;
}

static int tea575x_s_ctrl(struct v4l2_ctrl *c)
{
	struct radio_tea5777 *tea =
		container_of(c->handler, struct radio_tea5777, ctrl_handler);

Annotation

Implementation Notes