brintos

brintos / linux-shallow public Read only

0
0
Text · 13.9 KiB · 1b038b2 Raw
446 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  cx18 firmware functions4 *5 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>6 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>7 */8 9#include "cx18-driver.h"10#include "cx18-io.h"11#include "cx18-scb.h"12#include "cx18-irq.h"13#include "cx18-firmware.h"14#include "cx18-cards.h"15#include <linux/firmware.h>16 17#define CX18_PROC_SOFT_RESET		0xc7001018#define CX18_DDR_SOFT_RESET		0xc7001419#define CX18_CLOCK_SELECT1		0xc7100020#define CX18_CLOCK_SELECT2		0xc7100421#define CX18_HALF_CLOCK_SELECT1		0xc7100822#define CX18_HALF_CLOCK_SELECT2		0xc7100C23#define CX18_CLOCK_POLARITY1		0xc7101024#define CX18_CLOCK_POLARITY2		0xc7101425#define CX18_ADD_DELAY_ENABLE1		0xc7101826#define CX18_ADD_DELAY_ENABLE2		0xc7101C27#define CX18_CLOCK_ENABLE1		0xc7102028#define CX18_CLOCK_ENABLE2		0xc7102429 30#define CX18_REG_BUS_TIMEOUT_EN		0xc7202431 32#define CX18_FAST_CLOCK_PLL_INT		0xc7800033#define CX18_FAST_CLOCK_PLL_FRAC	0xc7800434#define CX18_FAST_CLOCK_PLL_POST	0xc7800835#define CX18_FAST_CLOCK_PLL_PRESCALE	0xc7800C36#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc7801037 38#define CX18_SLOW_CLOCK_PLL_INT		0xc7801439#define CX18_SLOW_CLOCK_PLL_FRAC	0xc7801840#define CX18_SLOW_CLOCK_PLL_POST	0xc7801C41#define CX18_MPEG_CLOCK_PLL_INT		0xc7804042#define CX18_MPEG_CLOCK_PLL_FRAC	0xc7804443#define CX18_MPEG_CLOCK_PLL_POST	0xc7804844#define CX18_PLL_POWER_DOWN		0xc7808845#define CX18_SW1_INT_STATUS             0xc7310446#define CX18_SW1_INT_ENABLE_PCI         0xc7311C47#define CX18_SW2_INT_SET                0xc7314048#define CX18_SW2_INT_STATUS             0xc7314449#define CX18_ADEC_CONTROL		0xc7812050 51#define CX18_DDR_REQUEST_ENABLE		0xc8000052#define CX18_DDR_CHIP_CONFIG		0xc8000453#define CX18_DDR_REFRESH		0xc8000854#define CX18_DDR_TIMING1		0xc8000C55#define CX18_DDR_TIMING2		0xc8001056#define CX18_DDR_POWER_REG		0xc8001C57 58#define CX18_DDR_TUNE_LANE		0xc8004859#define CX18_DDR_INITIAL_EMRS		0xc8005460#define CX18_DDR_MB_PER_ROW_7		0xc8009C61#define CX18_DDR_BASE_63_ADDR		0xc804FC62 63#define CX18_WMB_CLIENT02		0xc9010864#define CX18_WMB_CLIENT05		0xc9011465#define CX18_WMB_CLIENT06		0xc9011866#define CX18_WMB_CLIENT07		0xc9011C67#define CX18_WMB_CLIENT08		0xc9012068#define CX18_WMB_CLIENT09		0xc9012469#define CX18_WMB_CLIENT10		0xc9012870#define CX18_WMB_CLIENT11		0xc9012C71#define CX18_WMB_CLIENT12		0xc9013072#define CX18_WMB_CLIENT13		0xc9013473#define CX18_WMB_CLIENT14		0xc9013874 75#define CX18_DSP0_INTERRUPT_MASK	0xd0004C76 77#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */78#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */79 80struct cx18_apu_rom_seghdr {81	u32 sync1;82	u32 sync2;83	u32 addr;84	u32 size;85};86 87static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)88{89	const struct firmware *fw = NULL;90	int i, j;91	unsigned size;92	u32 __iomem *dst = (u32 __iomem *)mem;93	const u32 *src;94 95	if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {96		CX18_ERR("Unable to open firmware %s\n", fn);97		CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");98		return -ENOMEM;99	}100 101	src = (const u32 *)fw->data;102 103	for (i = 0; i < fw->size; i += 4096) {104		cx18_setup_page(cx, i);105		for (j = i; j < fw->size && j < i + 4096; j += 4) {106			/* no need for endianness conversion on the ppc */107			cx18_raw_writel(cx, *src, dst);108			if (cx18_raw_readl(cx, dst) != *src) {109				CX18_ERR("Mismatch at offset %x\n", i);110				release_firmware(fw);111				cx18_setup_page(cx, 0);112				return -EIO;113			}114			dst++;115			src++;116		}117	}118	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))119		CX18_INFO("loaded %s firmware (%zu bytes)\n", fn, fw->size);120	size = fw->size;121	release_firmware(fw);122	cx18_setup_page(cx, SCB_OFFSET);123	return size;124}125 126static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,127				u32 *entry_addr)128{129	const struct firmware *fw = NULL;130	int i, j;131	unsigned size;132	const u32 *src;133	struct cx18_apu_rom_seghdr seghdr;134	const u8 *vers;135	u32 offset = 0;136	u32 apu_version = 0;137	int sz;138 139	if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {140		CX18_ERR("unable to open firmware %s\n", fn);141		CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");142		cx18_setup_page(cx, 0);143		return -ENOMEM;144	}145 146	*entry_addr = 0;147	src = (const u32 *)fw->data;148	vers = fw->data + sizeof(seghdr);149	sz = fw->size;150 151	apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];152	while (offset + sizeof(seghdr) < fw->size) {153		const __le32 *shptr = (__force __le32 *)src + offset / 4;154 155		seghdr.sync1 = le32_to_cpu(shptr[0]);156		seghdr.sync2 = le32_to_cpu(shptr[1]);157		seghdr.addr = le32_to_cpu(shptr[2]);158		seghdr.size = le32_to_cpu(shptr[3]);159 160		offset += sizeof(seghdr);161		if (seghdr.sync1 != APU_ROM_SYNC1 ||162		    seghdr.sync2 != APU_ROM_SYNC2) {163			offset += seghdr.size;164			continue;165		}166		CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,167				seghdr.addr + seghdr.size - 1);168		if (*entry_addr == 0)169			*entry_addr = seghdr.addr;170		if (offset + seghdr.size > sz)171			break;172		for (i = 0; i < seghdr.size; i += 4096) {173			cx18_setup_page(cx, seghdr.addr + i);174			for (j = i; j < seghdr.size && j < i + 4096; j += 4) {175				/* no need for endianness conversion on the ppc */176				cx18_raw_writel(cx, src[(offset + j) / 4],177						dst + seghdr.addr + j);178				if (cx18_raw_readl(cx, dst + seghdr.addr + j)179				    != src[(offset + j) / 4]) {180					CX18_ERR("Mismatch at offset %x\n",181						 offset + j);182					release_firmware(fw);183					cx18_setup_page(cx, 0);184					return -EIO;185				}186			}187		}188		offset += seghdr.size;189	}190	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))191		CX18_INFO("loaded %s firmware V%08x (%zu bytes)\n",192				fn, apu_version, fw->size);193	size = fw->size;194	release_firmware(fw);195	cx18_setup_page(cx, 0);196	return size;197}198 199void cx18_halt_firmware(struct cx18 *cx)200{201	CX18_DEBUG_INFO("Preparing for firmware halt.\n");202	cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,203				  0x0000000F, 0x000F000F);204	cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,205				  0x00000002, 0x00020002);206}207 208void cx18_init_power(struct cx18 *cx, int lowpwr)209{210	/* power-down Spare and AOM PLLs */211	/* power-up fast, slow and mpeg PLLs */212	cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);213 214	/* ADEC out of sleep */215	cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,216				  0x00000000, 0x00020002);217 218	/*219	 * The PLL parameters are based on the external crystal frequency that220	 * would ideally be:221	 *222	 * NTSC Color subcarrier freq * 8 =223	 *	4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz224	 *225	 * The accidents of history and rationale that explain from where this226	 * combination of magic numbers originate can be found in:227	 *228	 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in229	 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80230	 *231	 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the232	 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83233	 *234	 * As Mike Bradley has rightly pointed out, it's not the exact crystal235	 * frequency that matters, only that all parts of the driver and236	 * firmware are using the same value (close to the ideal value).237	 *238	 * Since I have a strong suspicion that, if the firmware ever assumes a239	 * crystal value at all, it will assume 28.636360 MHz, the crystal240	 * freq used in calculations in this driver will be:241	 *242	 *	xtal_freq = 28.636360 MHz243	 *244	 * an error of less than 0.13 ppm which is way, way better than any off245	 * the shelf crystal will have for accuracy anyway.246	 *247	 * Below I aim to run the PLLs' VCOs near 400 MHz to minimize errors.248	 *249	 * Many thanks to Jeff Campbell and Mike Bradley for their extensive250	 * investigation, experimentation, testing, and suggested solutions of251	 * audio/video sync problems with SVideo and CVBS captures.252	 */253 254	/* the fast clock is at 200/245 MHz */255	/* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/256	/* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/257	cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);258	cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,259						CX18_FAST_CLOCK_PLL_FRAC);260 261	cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);262	cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);263	cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);264 265	/* set slow clock to 125/120 MHz */266	/* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */267	/* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */268	cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);269	cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,270						CX18_SLOW_CLOCK_PLL_FRAC);271	cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);272 273	/* mpeg clock pll 54MHz */274	/* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */275	cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);276	cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);277	cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);278 279	/* Defaults */280	/* APU = SC or SC/2 = 125/62.5 */281	/* EPU = SC = 125 */282	/* DDR = FC = 180 */283	/* ENC = SC = 125 */284	/* AI1 = SC = 125 */285	/* VIM2 = disabled */286	/* PCI = FC/2 = 90 */287	/* AI2 = disabled */288	/* DEMUX = disabled */289	/* AO = SC/2 = 62.5 */290	/* SER = 54MHz */291	/* VFC = disabled */292	/* USB = disabled */293 294	if (lowpwr) {295		cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,296					  0x00000020, 0xFFFFFFFF);297		cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,298					  0x00000004, 0xFFFFFFFF);299	} else {300		/* This doesn't explicitly set every clock select */301		cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,302					  0x00000004, 0x00060006);303		cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,304					  0x00000006, 0x00060006);305	}306 307	cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,308				  0x00000002, 0xFFFFFFFF);309	cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,310				  0x00000104, 0xFFFFFFFF);311	cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,312				  0x00009026, 0xFFFFFFFF);313	cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,314				  0x00003105, 0xFFFFFFFF);315}316 317void cx18_init_memory(struct cx18 *cx)318{319	cx18_msleep_timeout(10, 0);320	cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,321				  0x00000000, 0x00010001);322	cx18_msleep_timeout(10, 0);323 324	cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);325 326	cx18_msleep_timeout(10, 0);327 328	cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);329	cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);330	cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);331 332	cx18_msleep_timeout(10, 0);333 334	/* Initialize DQS pad time */335	cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);336	cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);337 338	cx18_msleep_timeout(10, 0);339 340	cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,341				  0x00000000, 0x00020002);342	cx18_msleep_timeout(10, 0);343 344	/* use power-down mode when idle */345	cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);346 347	cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,348				  0x00000001, 0x00010001);349 350	cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);351	cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);352 353	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);  /* AO */354	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);  /* AI2 */355	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */356	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);  /* AI1 */357	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */358	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);  /* ME */359	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);  /* ENC */360	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);  /* PK */361	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);  /* RC */362	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);  /* AVO */363}364 365#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"366#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"367 368int cx18_firmware_init(struct cx18 *cx)369{370	u32 fw_entry_addr;371	int sz, retries;372	u32 api_args[MAX_MB_ARGUMENTS];373 374	/* Allow chip to control CLKRUN */375	cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);376 377	/* Stop the firmware */378	cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,379				  0x0000000F, 0x000F000F);380 381	cx18_msleep_timeout(1, 0);382 383	/* If the CPU is still running */384	if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {385		CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);386		return -EIO;387	}388 389	cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);390	cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);391 392	sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);393	if (sz <= 0)394		return sz;395 396	/* The SCB & IPC area *must* be correct before starting the firmwares */397	cx18_init_scb(cx);398 399	fw_entry_addr = 0;400	sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,401				&fw_entry_addr);402	if (sz <= 0)403		return sz;404 405	/* Start the CPU. The CPU will take care of the APU for us. */406	cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,407				  0x00000000, 0x00080008);408 409	/* Wait up to 500 ms for the APU to come out of reset */410	for (retries = 0;411	     retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;412	     retries++)413		cx18_msleep_timeout(10, 0);414 415	cx18_msleep_timeout(200, 0);416 417	if (retries == 50 &&418	    (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {419		CX18_ERR("Could not start the CPU\n");420		return -EIO;421	}422 423	/*424	 * The CPU had once before set up to receive an interrupt for it's425	 * outgoing IRQ_CPU_TO_EPU_ACK to us.  If it ever does this, we get an426	 * interrupt when it sends us an ack, but by the time we process it,427	 * that flag in the SW2 status register has been cleared by the CPU428	 * firmware.  We'll prevent that not so useful condition from happening429	 * by clearing the CPU's interrupt enables for Ack IRQ's we want to430	 * process.431	 */432	cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);433 434	/* Try a benign command to see if the CPU is alive and well */435	sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);436	if (sz < 0)437		return sz;438 439	/* initialize GPIO */440	cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);441	return 0;442}443 444MODULE_FIRMWARE(CX18_CPU_FIRMWARE);445MODULE_FIRMWARE(CX18_APU_FIRMWARE);446