18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "mxl111sf-gpio.h"
98c2ecf20Sopenharmony_ci#include "mxl111sf-i2c.h"
108c2ecf20Sopenharmony_ci#include "mxl111sf.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------- */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define MXL_GPIO_MUX_REG_0 0x84
158c2ecf20Sopenharmony_ci#define MXL_GPIO_MUX_REG_1 0x89
168c2ecf20Sopenharmony_ci#define MXL_GPIO_MUX_REG_2 0x82
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define MXL_GPIO_DIR_INPUT  0
198c2ecf20Sopenharmony_ci#define MXL_GPIO_DIR_OUTPUT 1
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	int ret;
258c2ecf20Sopenharmony_ci	u8 tmp;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	mxl_debug_adv("(%d, %d)", pin, val);
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	if ((pin > 0) && (pin < 8)) {
308c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, 0x19, &tmp);
318c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
328c2ecf20Sopenharmony_ci			goto fail;
338c2ecf20Sopenharmony_ci		tmp &= ~(1 << (pin - 1));
348c2ecf20Sopenharmony_ci		tmp |= (val << (pin - 1));
358c2ecf20Sopenharmony_ci		ret = mxl111sf_write_reg(state, 0x19, tmp);
368c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
378c2ecf20Sopenharmony_ci			goto fail;
388c2ecf20Sopenharmony_ci	} else if (pin <= 10) {
398c2ecf20Sopenharmony_ci		if (pin == 0)
408c2ecf20Sopenharmony_ci			pin += 7;
418c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, 0x30, &tmp);
428c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
438c2ecf20Sopenharmony_ci			goto fail;
448c2ecf20Sopenharmony_ci		tmp &= ~(1 << (pin - 3));
458c2ecf20Sopenharmony_ci		tmp |= (val << (pin - 3));
468c2ecf20Sopenharmony_ci		ret = mxl111sf_write_reg(state, 0x30, tmp);
478c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
488c2ecf20Sopenharmony_ci			goto fail;
498c2ecf20Sopenharmony_ci	} else
508c2ecf20Sopenharmony_ci		ret = -EINVAL;
518c2ecf20Sopenharmony_cifail:
528c2ecf20Sopenharmony_ci	return ret;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	int ret;
588c2ecf20Sopenharmony_ci	u8 tmp;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	mxl_debug("(0x%02x)", pin);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	*val = 0;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	switch (pin) {
658c2ecf20Sopenharmony_ci	case 0:
668c2ecf20Sopenharmony_ci	case 1:
678c2ecf20Sopenharmony_ci	case 2:
688c2ecf20Sopenharmony_ci	case 3:
698c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, 0x23, &tmp);
708c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
718c2ecf20Sopenharmony_ci			goto fail;
728c2ecf20Sopenharmony_ci		*val = (tmp >> (pin + 4)) & 0x01;
738c2ecf20Sopenharmony_ci		break;
748c2ecf20Sopenharmony_ci	case 4:
758c2ecf20Sopenharmony_ci	case 5:
768c2ecf20Sopenharmony_ci	case 6:
778c2ecf20Sopenharmony_ci	case 7:
788c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, 0x2f, &tmp);
798c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
808c2ecf20Sopenharmony_ci			goto fail;
818c2ecf20Sopenharmony_ci		*val = (tmp >> pin) & 0x01;
828c2ecf20Sopenharmony_ci		break;
838c2ecf20Sopenharmony_ci	case 8:
848c2ecf20Sopenharmony_ci	case 9:
858c2ecf20Sopenharmony_ci	case 10:
868c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, 0x22, &tmp);
878c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
888c2ecf20Sopenharmony_ci			goto fail;
898c2ecf20Sopenharmony_ci		*val = (tmp >> (pin - 3)) & 0x01;
908c2ecf20Sopenharmony_ci		break;
918c2ecf20Sopenharmony_ci	default:
928c2ecf20Sopenharmony_ci		return -EINVAL; /* invalid pin */
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_cifail:
958c2ecf20Sopenharmony_ci	return ret;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistruct mxl_gpio_cfg {
998c2ecf20Sopenharmony_ci	u8 pin;
1008c2ecf20Sopenharmony_ci	u8 dir;
1018c2ecf20Sopenharmony_ci	u8 val;
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
1058c2ecf20Sopenharmony_ci				     struct mxl_gpio_cfg *gpio_cfg)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	int ret;
1088c2ecf20Sopenharmony_ci	u8 tmp;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	switch (gpio_cfg->pin) {
1138c2ecf20Sopenharmony_ci	case 0:
1148c2ecf20Sopenharmony_ci	case 1:
1158c2ecf20Sopenharmony_ci	case 2:
1168c2ecf20Sopenharmony_ci	case 3:
1178c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
1188c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
1198c2ecf20Sopenharmony_ci			goto fail;
1208c2ecf20Sopenharmony_ci		tmp &= ~(1 << (gpio_cfg->pin + 4));
1218c2ecf20Sopenharmony_ci		tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
1228c2ecf20Sopenharmony_ci		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
1238c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
1248c2ecf20Sopenharmony_ci			goto fail;
1258c2ecf20Sopenharmony_ci		break;
1268c2ecf20Sopenharmony_ci	case 4:
1278c2ecf20Sopenharmony_ci	case 5:
1288c2ecf20Sopenharmony_ci	case 6:
1298c2ecf20Sopenharmony_ci	case 7:
1308c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
1318c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
1328c2ecf20Sopenharmony_ci			goto fail;
1338c2ecf20Sopenharmony_ci		tmp &= ~(1 << gpio_cfg->pin);
1348c2ecf20Sopenharmony_ci		tmp |= (gpio_cfg->dir << gpio_cfg->pin);
1358c2ecf20Sopenharmony_ci		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
1368c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
1378c2ecf20Sopenharmony_ci			goto fail;
1388c2ecf20Sopenharmony_ci		break;
1398c2ecf20Sopenharmony_ci	case 8:
1408c2ecf20Sopenharmony_ci	case 9:
1418c2ecf20Sopenharmony_ci	case 10:
1428c2ecf20Sopenharmony_ci		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
1438c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
1448c2ecf20Sopenharmony_ci			goto fail;
1458c2ecf20Sopenharmony_ci		tmp &= ~(1 << (gpio_cfg->pin - 3));
1468c2ecf20Sopenharmony_ci		tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
1478c2ecf20Sopenharmony_ci		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
1488c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
1498c2ecf20Sopenharmony_ci			goto fail;
1508c2ecf20Sopenharmony_ci		break;
1518c2ecf20Sopenharmony_ci	default:
1528c2ecf20Sopenharmony_ci		return -EINVAL; /* invalid pin */
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
1568c2ecf20Sopenharmony_ci		mxl111sf_set_gpo_state(state,
1578c2ecf20Sopenharmony_ci				       gpio_cfg->pin, gpio_cfg->val) :
1588c2ecf20Sopenharmony_ci		mxl111sf_get_gpi_state(state,
1598c2ecf20Sopenharmony_ci				       gpio_cfg->pin, &gpio_cfg->val);
1608c2ecf20Sopenharmony_ci	mxl_fail(ret);
1618c2ecf20Sopenharmony_cifail:
1628c2ecf20Sopenharmony_ci	return ret;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
1668c2ecf20Sopenharmony_ci				   int gpio, int direction, int val)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct mxl_gpio_cfg gpio_config = {
1698c2ecf20Sopenharmony_ci		.pin = gpio,
1708c2ecf20Sopenharmony_ci		.dir = direction,
1718c2ecf20Sopenharmony_ci		.val = val,
1728c2ecf20Sopenharmony_ci	};
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	mxl_debug("(%d, %d, %d)", gpio, direction, val);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	return mxl111sf_config_gpio_pins(state, &gpio_config);
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------- */
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci#define PIN_MUX_MPEG_MODE_MASK          0x40   /* 0x17 <6> */
1828c2ecf20Sopenharmony_ci#define PIN_MUX_MPEG_PAR_EN_MASK        0x01   /* 0x18 <0> */
1838c2ecf20Sopenharmony_ci#define PIN_MUX_MPEG_SER_EN_MASK        0x02   /* 0x18 <1> */
1848c2ecf20Sopenharmony_ci#define PIN_MUX_MPG_IN_MUX_MASK         0x80   /* 0x3D <7> */
1858c2ecf20Sopenharmony_ci#define PIN_MUX_BT656_ENABLE_MASK       0x04   /* 0x12 <2> */
1868c2ecf20Sopenharmony_ci#define PIN_MUX_I2S_ENABLE_MASK         0x40   /* 0x15 <6> */
1878c2ecf20Sopenharmony_ci#define PIN_MUX_SPI_MODE_MASK           0x10   /* 0x3D <4> */
1888c2ecf20Sopenharmony_ci#define PIN_MUX_MCLK_EN_CTRL_MASK       0x10   /* 0x82 <4> */
1898c2ecf20Sopenharmony_ci#define PIN_MUX_MPSYN_EN_CTRL_MASK      0x20   /* 0x82 <5> */
1908c2ecf20Sopenharmony_ci#define PIN_MUX_MDVAL_EN_CTRL_MASK      0x40   /* 0x82 <6> */
1918c2ecf20Sopenharmony_ci#define PIN_MUX_MPERR_EN_CTRL_MASK      0x80   /* 0x82 <7> */
1928c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_0_MASK          0x10   /* 0x84 <4> */
1938c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_1_MASK          0x20   /* 0x84 <5> */
1948c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_2_MASK          0x40   /* 0x84 <6> */
1958c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_3_MASK          0x80   /* 0x84 <7> */
1968c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_4_MASK          0x10   /* 0x89 <4> */
1978c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_5_MASK          0x20   /* 0x89 <5> */
1988c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_6_MASK          0x40   /* 0x89 <6> */
1998c2ecf20Sopenharmony_ci#define PIN_MUX_MDAT_EN_7_MASK          0x80   /* 0x89 <7> */
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ciint mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
2028c2ecf20Sopenharmony_ci				  enum mxl111sf_mux_config pin_mux_config)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	u8 r12, r15, r17, r18, r3D, r82, r84, r89;
2058c2ecf20Sopenharmony_ci	int ret;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	mxl_debug("(%d)", pin_mux_config);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x17, &r17);
2108c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2118c2ecf20Sopenharmony_ci		goto fail;
2128c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x18, &r18);
2138c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2148c2ecf20Sopenharmony_ci		goto fail;
2158c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x12, &r12);
2168c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2178c2ecf20Sopenharmony_ci		goto fail;
2188c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x15, &r15);
2198c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2208c2ecf20Sopenharmony_ci		goto fail;
2218c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x82, &r82);
2228c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2238c2ecf20Sopenharmony_ci		goto fail;
2248c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x84, &r84);
2258c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2268c2ecf20Sopenharmony_ci		goto fail;
2278c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x89, &r89);
2288c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2298c2ecf20Sopenharmony_ci		goto fail;
2308c2ecf20Sopenharmony_ci	ret = mxl111sf_read_reg(state, 0x3D, &r3D);
2318c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
2328c2ecf20Sopenharmony_ci		goto fail;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	switch (pin_mux_config) {
2358c2ecf20Sopenharmony_ci	case PIN_MUX_TS_OUT_PARALLEL:
2368c2ecf20Sopenharmony_ci		/* mpeg_mode = 1 */
2378c2ecf20Sopenharmony_ci		r17 |= PIN_MUX_MPEG_MODE_MASK;
2388c2ecf20Sopenharmony_ci		/* mpeg_par_en = 1 */
2398c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
2408c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 0 */
2418c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
2428c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
2438c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
2448c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
2458c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
2468c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
2478c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
2488c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
2498c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
2508c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 1 */
2518c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
2528c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 1 */
2538c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
2548c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 1 */
2558c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
2568c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 1 */
2578c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
2588c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0xF */
2598c2ecf20Sopenharmony_ci		r84 |= 0xF0;
2608c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0xF */
2618c2ecf20Sopenharmony_ci		r89 |= 0xF0;
2628c2ecf20Sopenharmony_ci		break;
2638c2ecf20Sopenharmony_ci	case PIN_MUX_TS_OUT_SERIAL:
2648c2ecf20Sopenharmony_ci		/* mpeg_mode = 1 */
2658c2ecf20Sopenharmony_ci		r17 |= PIN_MUX_MPEG_MODE_MASK;
2668c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
2678c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
2688c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 1 */
2698c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
2708c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
2718c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
2728c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
2738c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
2748c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
2758c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
2768c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
2778c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
2788c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 1 */
2798c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
2808c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 1 */
2818c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
2828c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 1 */
2838c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
2848c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 1 */
2858c2ecf20Sopenharmony_ci		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
2868c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0xF */
2878c2ecf20Sopenharmony_ci		r84 |= 0xF0;
2888c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0xF */
2898c2ecf20Sopenharmony_ci		r89 |= 0xF0;
2908c2ecf20Sopenharmony_ci		break;
2918c2ecf20Sopenharmony_ci	case PIN_MUX_GPIO_MODE:
2928c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
2938c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
2948c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
2958c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
2968c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 0 */
2978c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
2988c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
2998c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
3008c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
3018c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
3028c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
3038c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
3048c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
3058c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
3068c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
3078c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
3088c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
3098c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
3108c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
3118c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
3128c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
3138c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
3148c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
3158c2ecf20Sopenharmony_ci		r84 &= 0x0F;
3168c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
3178c2ecf20Sopenharmony_ci		r89 &= 0x0F;
3188c2ecf20Sopenharmony_ci		break;
3198c2ecf20Sopenharmony_ci	case PIN_MUX_TS_SERIAL_IN_MODE_0:
3208c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
3218c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
3228c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
3238c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
3248c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 1 */
3258c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
3268c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
3278c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
3288c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
3298c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
3308c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
3318c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
3328c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
3338c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
3348c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
3358c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
3368c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
3378c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
3388c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
3398c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
3408c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
3418c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
3428c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
3438c2ecf20Sopenharmony_ci		r84 &= 0x0F;
3448c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
3458c2ecf20Sopenharmony_ci		r89 &= 0x0F;
3468c2ecf20Sopenharmony_ci		break;
3478c2ecf20Sopenharmony_ci	case PIN_MUX_TS_SERIAL_IN_MODE_1:
3488c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
3498c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
3508c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
3518c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
3528c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 1 */
3538c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
3548c2ecf20Sopenharmony_ci		/* mpg_in_mux = 1 */
3558c2ecf20Sopenharmony_ci		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
3568c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
3578c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
3588c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
3598c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
3608c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
3618c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
3628c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
3638c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
3648c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
3658c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
3668c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
3678c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
3688c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
3698c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
3708c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
3718c2ecf20Sopenharmony_ci		r84 &= 0x0F;
3728c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
3738c2ecf20Sopenharmony_ci		r89 &= 0x0F;
3748c2ecf20Sopenharmony_ci		break;
3758c2ecf20Sopenharmony_ci	case PIN_MUX_TS_SPI_IN_MODE_1:
3768c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
3778c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
3788c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
3798c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
3808c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 1 */
3818c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
3828c2ecf20Sopenharmony_ci		/* mpg_in_mux = 1 */
3838c2ecf20Sopenharmony_ci		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
3848c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
3858c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
3868c2ecf20Sopenharmony_ci		/* i2s_enable = 1 */
3878c2ecf20Sopenharmony_ci		r15 |= PIN_MUX_I2S_ENABLE_MASK;
3888c2ecf20Sopenharmony_ci		/* spi_mode = 1 */
3898c2ecf20Sopenharmony_ci		r3D |= PIN_MUX_SPI_MODE_MASK;
3908c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
3918c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
3928c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
3938c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
3948c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
3958c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
3968c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
3978c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
3988c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
3998c2ecf20Sopenharmony_ci		r84 &= 0x0F;
4008c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
4018c2ecf20Sopenharmony_ci		r89 &= 0x0F;
4028c2ecf20Sopenharmony_ci		break;
4038c2ecf20Sopenharmony_ci	case PIN_MUX_TS_SPI_IN_MODE_0:
4048c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
4058c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
4068c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
4078c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
4088c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 1 */
4098c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
4108c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
4118c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
4128c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
4138c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
4148c2ecf20Sopenharmony_ci		/* i2s_enable = 1 */
4158c2ecf20Sopenharmony_ci		r15 |= PIN_MUX_I2S_ENABLE_MASK;
4168c2ecf20Sopenharmony_ci		/* spi_mode = 1 */
4178c2ecf20Sopenharmony_ci		r3D |= PIN_MUX_SPI_MODE_MASK;
4188c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
4198c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
4208c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
4218c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
4228c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
4238c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
4248c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
4258c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
4268c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
4278c2ecf20Sopenharmony_ci		r84 &= 0x0F;
4288c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
4298c2ecf20Sopenharmony_ci		r89 &= 0x0F;
4308c2ecf20Sopenharmony_ci		break;
4318c2ecf20Sopenharmony_ci	case PIN_MUX_TS_PARALLEL_IN:
4328c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
4338c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
4348c2ecf20Sopenharmony_ci		/* mpeg_par_en = 1 */
4358c2ecf20Sopenharmony_ci		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
4368c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 0 */
4378c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
4388c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
4398c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
4408c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
4418c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
4428c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
4438c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
4448c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
4458c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
4468c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
4478c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
4488c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
4498c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
4508c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
4518c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
4528c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
4538c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
4548c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
4558c2ecf20Sopenharmony_ci		r84 &= 0x0F;
4568c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
4578c2ecf20Sopenharmony_ci		r89 &= 0x0F;
4588c2ecf20Sopenharmony_ci		break;
4598c2ecf20Sopenharmony_ci	case PIN_MUX_BT656_I2S_MODE:
4608c2ecf20Sopenharmony_ci		/* mpeg_mode = 0 */
4618c2ecf20Sopenharmony_ci		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
4628c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
4638c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
4648c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 0 */
4658c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
4668c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
4678c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
4688c2ecf20Sopenharmony_ci		/* bt656_enable = 1 */
4698c2ecf20Sopenharmony_ci		r12 |= PIN_MUX_BT656_ENABLE_MASK;
4708c2ecf20Sopenharmony_ci		/* i2s_enable = 1 */
4718c2ecf20Sopenharmony_ci		r15 |= PIN_MUX_I2S_ENABLE_MASK;
4728c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
4738c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
4748c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
4758c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
4768c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
4778c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
4788c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
4798c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
4808c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
4818c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
4828c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
4838c2ecf20Sopenharmony_ci		r84 &= 0x0F;
4848c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
4858c2ecf20Sopenharmony_ci		r89 &= 0x0F;
4868c2ecf20Sopenharmony_ci		break;
4878c2ecf20Sopenharmony_ci	case PIN_MUX_DEFAULT:
4888c2ecf20Sopenharmony_ci	default:
4898c2ecf20Sopenharmony_ci		/* mpeg_mode = 1 */
4908c2ecf20Sopenharmony_ci		r17 |= PIN_MUX_MPEG_MODE_MASK;
4918c2ecf20Sopenharmony_ci		/* mpeg_par_en = 0 */
4928c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
4938c2ecf20Sopenharmony_ci		/* mpeg_ser_en = 0 */
4948c2ecf20Sopenharmony_ci		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
4958c2ecf20Sopenharmony_ci		/* mpg_in_mux = 0 */
4968c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
4978c2ecf20Sopenharmony_ci		/* bt656_enable = 0 */
4988c2ecf20Sopenharmony_ci		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
4998c2ecf20Sopenharmony_ci		/* i2s_enable = 0 */
5008c2ecf20Sopenharmony_ci		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
5018c2ecf20Sopenharmony_ci		/* spi_mode = 0 */
5028c2ecf20Sopenharmony_ci		r3D &= ~PIN_MUX_SPI_MODE_MASK;
5038c2ecf20Sopenharmony_ci		/* mclk_en_ctrl = 0 */
5048c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
5058c2ecf20Sopenharmony_ci		/* mperr_en_ctrl = 0 */
5068c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
5078c2ecf20Sopenharmony_ci		/* mdval_en_ctrl = 0 */
5088c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
5098c2ecf20Sopenharmony_ci		/* mpsyn_en_ctrl = 0 */
5108c2ecf20Sopenharmony_ci		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
5118c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[3:0] = 0x0 */
5128c2ecf20Sopenharmony_ci		r84 &= 0x0F;
5138c2ecf20Sopenharmony_ci		/* mdat_en_ctrl[7:4] = 0x0 */
5148c2ecf20Sopenharmony_ci		r89 &= 0x0F;
5158c2ecf20Sopenharmony_ci		break;
5168c2ecf20Sopenharmony_ci	}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x17, r17);
5198c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5208c2ecf20Sopenharmony_ci		goto fail;
5218c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x18, r18);
5228c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5238c2ecf20Sopenharmony_ci		goto fail;
5248c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x12, r12);
5258c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5268c2ecf20Sopenharmony_ci		goto fail;
5278c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x15, r15);
5288c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5298c2ecf20Sopenharmony_ci		goto fail;
5308c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x82, r82);
5318c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5328c2ecf20Sopenharmony_ci		goto fail;
5338c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x84, r84);
5348c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5358c2ecf20Sopenharmony_ci		goto fail;
5368c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x89, r89);
5378c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5388c2ecf20Sopenharmony_ci		goto fail;
5398c2ecf20Sopenharmony_ci	ret = mxl111sf_write_reg(state, 0x3D, r3D);
5408c2ecf20Sopenharmony_ci	if (mxl_fail(ret))
5418c2ecf20Sopenharmony_ci		goto fail;
5428c2ecf20Sopenharmony_cifail:
5438c2ecf20Sopenharmony_ci	return ret;
5448c2ecf20Sopenharmony_ci}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------- */
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_cistatic int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
5498c2ecf20Sopenharmony_ci{
5508c2ecf20Sopenharmony_ci	return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
5518c2ecf20Sopenharmony_ci}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_cistatic int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
5548c2ecf20Sopenharmony_ci{
5558c2ecf20Sopenharmony_ci	u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
5568c2ecf20Sopenharmony_ci	int i, ret;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	mxl_debug("()");
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	for (i = 3; i < 8; i++) {
5618c2ecf20Sopenharmony_ci		ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
5628c2ecf20Sopenharmony_ci		if (mxl_fail(ret))
5638c2ecf20Sopenharmony_ci			break;
5648c2ecf20Sopenharmony_ci	}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	return ret;
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci#define PCA9534_I2C_ADDR (0x40 >> 1)
5708c2ecf20Sopenharmony_cistatic int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	u8 w[2] = { 1, 0 };
5738c2ecf20Sopenharmony_ci	u8 r = 0;
5748c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
5758c2ecf20Sopenharmony_ci		{ .addr = PCA9534_I2C_ADDR,
5768c2ecf20Sopenharmony_ci		  .flags = 0, .buf = w, .len = 1 },
5778c2ecf20Sopenharmony_ci		{ .addr = PCA9534_I2C_ADDR,
5788c2ecf20Sopenharmony_ci		  .flags = I2C_M_RD, .buf = &r, .len = 1 },
5798c2ecf20Sopenharmony_ci	};
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	mxl_debug("(%d, %d)", gpio, val);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	/* read current GPIO levels from flip-flop */
5848c2ecf20Sopenharmony_ci	i2c_transfer(&state->d->i2c_adap, msg, 2);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	/* prepare write buffer with current GPIO levels */
5878c2ecf20Sopenharmony_ci	msg[0].len = 2;
5888c2ecf20Sopenharmony_ci#if 0
5898c2ecf20Sopenharmony_ci	w[0] = 1;
5908c2ecf20Sopenharmony_ci#endif
5918c2ecf20Sopenharmony_ci	w[1] = r;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	/* clear the desired GPIO */
5948c2ecf20Sopenharmony_ci	w[1] &= ~(1 << gpio);
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	/* set the desired GPIO value */
5978c2ecf20Sopenharmony_ci	w[1] |= ((val ? 1 : 0) << gpio);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	/* write new GPIO levels to flip-flop */
6008c2ecf20Sopenharmony_ci	i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	return 0;
6038c2ecf20Sopenharmony_ci}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic int pca9534_init_port_expander(struct mxl111sf_state *state)
6068c2ecf20Sopenharmony_ci{
6078c2ecf20Sopenharmony_ci	u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
6108c2ecf20Sopenharmony_ci		.addr = PCA9534_I2C_ADDR,
6118c2ecf20Sopenharmony_ci		.flags = 0, .buf = w, .len = 2
6128c2ecf20Sopenharmony_ci	};
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	mxl_debug("()");
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	i2c_transfer(&state->d->i2c_adap, &msg, 1);
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	/* configure all pins as outputs */
6198c2ecf20Sopenharmony_ci	w[0] = 3;
6208c2ecf20Sopenharmony_ci	w[1] = 0;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	i2c_transfer(&state->d->i2c_adap, &msg, 1);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	return 0;
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ciint mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
6288c2ecf20Sopenharmony_ci{
6298c2ecf20Sopenharmony_ci	mxl_debug("(%d, %d)", gpio, val);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	switch (state->gpio_port_expander) {
6328c2ecf20Sopenharmony_ci	default:
6338c2ecf20Sopenharmony_ci		mxl_printk(KERN_ERR,
6348c2ecf20Sopenharmony_ci			   "gpio_port_expander undefined, assuming PCA9534");
6358c2ecf20Sopenharmony_ci		fallthrough;
6368c2ecf20Sopenharmony_ci	case mxl111sf_PCA9534:
6378c2ecf20Sopenharmony_ci		return pca9534_set_gpio(state, gpio, val);
6388c2ecf20Sopenharmony_ci	case mxl111sf_gpio_hw:
6398c2ecf20Sopenharmony_ci		return mxl111sf_hw_set_gpio(state, gpio, val);
6408c2ecf20Sopenharmony_ci	}
6418c2ecf20Sopenharmony_ci}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_cistatic int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	int ret;
6468c2ecf20Sopenharmony_ci	u8 w = 1;
6478c2ecf20Sopenharmony_ci	u8 r = 0;
6488c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
6498c2ecf20Sopenharmony_ci		{ .flags = 0,        .buf = &w, .len = 1 },
6508c2ecf20Sopenharmony_ci		{ .flags = I2C_M_RD, .buf = &r, .len = 1 },
6518c2ecf20Sopenharmony_ci	};
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	mxl_debug("()");
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	msg[0].addr = 0x70 >> 1;
6568c2ecf20Sopenharmony_ci	msg[1].addr = 0x70 >> 1;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	/* read current GPIO levels from flip-flop */
6598c2ecf20Sopenharmony_ci	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
6608c2ecf20Sopenharmony_ci	if (ret == 2) {
6618c2ecf20Sopenharmony_ci		state->port_expander_addr = msg[0].addr;
6628c2ecf20Sopenharmony_ci		state->gpio_port_expander = mxl111sf_PCA9534;
6638c2ecf20Sopenharmony_ci		mxl_debug("found port expander at 0x%02x",
6648c2ecf20Sopenharmony_ci			  state->port_expander_addr);
6658c2ecf20Sopenharmony_ci		return 0;
6668c2ecf20Sopenharmony_ci	}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	msg[0].addr = 0x40 >> 1;
6698c2ecf20Sopenharmony_ci	msg[1].addr = 0x40 >> 1;
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
6728c2ecf20Sopenharmony_ci	if (ret == 2) {
6738c2ecf20Sopenharmony_ci		state->port_expander_addr = msg[0].addr;
6748c2ecf20Sopenharmony_ci		state->gpio_port_expander = mxl111sf_PCA9534;
6758c2ecf20Sopenharmony_ci		mxl_debug("found port expander at 0x%02x",
6768c2ecf20Sopenharmony_ci			  state->port_expander_addr);
6778c2ecf20Sopenharmony_ci		return 0;
6788c2ecf20Sopenharmony_ci	}
6798c2ecf20Sopenharmony_ci	state->port_expander_addr = 0xff;
6808c2ecf20Sopenharmony_ci	state->gpio_port_expander = mxl111sf_gpio_hw;
6818c2ecf20Sopenharmony_ci	mxl_debug("using hardware gpio");
6828c2ecf20Sopenharmony_ci	return 0;
6838c2ecf20Sopenharmony_ci}
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ciint mxl111sf_init_port_expander(struct mxl111sf_state *state)
6868c2ecf20Sopenharmony_ci{
6878c2ecf20Sopenharmony_ci	mxl_debug("()");
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (0x00 == state->port_expander_addr)
6908c2ecf20Sopenharmony_ci		mxl111sf_probe_port_expander(state);
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	switch (state->gpio_port_expander) {
6938c2ecf20Sopenharmony_ci	default:
6948c2ecf20Sopenharmony_ci		mxl_printk(KERN_ERR,
6958c2ecf20Sopenharmony_ci			   "gpio_port_expander undefined, assuming PCA9534");
6968c2ecf20Sopenharmony_ci		fallthrough;
6978c2ecf20Sopenharmony_ci	case mxl111sf_PCA9534:
6988c2ecf20Sopenharmony_ci		return pca9534_init_port_expander(state);
6998c2ecf20Sopenharmony_ci	case mxl111sf_gpio_hw:
7008c2ecf20Sopenharmony_ci		return mxl111sf_hw_gpio_initialize(state);
7018c2ecf20Sopenharmony_ci	}
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ciint mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci/*	GPO:
7098c2ecf20Sopenharmony_ci *	3 - ATSC/MH#   | 1 = ATSC transport, 0 = MH transport      | default 0
7108c2ecf20Sopenharmony_ci *	4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset           | default 0
7118c2ecf20Sopenharmony_ci *	5 - ATSC_EN    | 1 = ATSC power enable, 0 = ATSC power off | default 0
7128c2ecf20Sopenharmony_ci *	6 - MH_RESET#  | 1 = MH enable, 0 = MH Reset               | default 0
7138c2ecf20Sopenharmony_ci *	7 - MH_EN      | 1 = MH power enable, 0 = MH power off     | default 0
7148c2ecf20Sopenharmony_ci */
7158c2ecf20Sopenharmony_ci	mxl_debug("(%d)", mode);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	switch (mode) {
7188c2ecf20Sopenharmony_ci	case MXL111SF_GPIO_MOD_MH:
7198c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 4, 0);
7208c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 5, 0);
7218c2ecf20Sopenharmony_ci		msleep(50);
7228c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 7, 1);
7238c2ecf20Sopenharmony_ci		msleep(50);
7248c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 6, 1);
7258c2ecf20Sopenharmony_ci		msleep(50);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 3, 0);
7288c2ecf20Sopenharmony_ci		break;
7298c2ecf20Sopenharmony_ci	case MXL111SF_GPIO_MOD_ATSC:
7308c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 6, 0);
7318c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 7, 0);
7328c2ecf20Sopenharmony_ci		msleep(50);
7338c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 5, 1);
7348c2ecf20Sopenharmony_ci		msleep(50);
7358c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 4, 1);
7368c2ecf20Sopenharmony_ci		msleep(50);
7378c2ecf20Sopenharmony_ci		mxl111sf_set_gpio(state, 3, 1);
7388c2ecf20Sopenharmony_ci		break;
7398c2ecf20Sopenharmony_ci	default: /* DVBT / STANDBY */
7408c2ecf20Sopenharmony_ci		mxl111sf_init_port_expander(state);
7418c2ecf20Sopenharmony_ci		break;
7428c2ecf20Sopenharmony_ci	}
7438c2ecf20Sopenharmony_ci	return 0;
7448c2ecf20Sopenharmony_ci}
745