^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Maxim Integrated MAX2175 RF to Bits tuner driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This driver & most of the hard coded values are based on the reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * application delivered by Maxim for this device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2016 Maxim Integrated Products
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2017 Renesas Electronics Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/max2175.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "max2175.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define DRIVER_NAME "max2175"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define mxm_dbg(ctx, fmt, arg...) dev_dbg(&ctx->client->dev, fmt, ## arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define mxm_err(ctx, fmt, arg...) dev_err(&ctx->client->dev, fmt, ## arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Rx mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct max2175_rxmode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum max2175_band band; /* Associated band */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 freq; /* Default freq in Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u8 i2s_word_size; /* Bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Register map to define preset values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct max2175_reg_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u8 idx; /* Register index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u8 val; /* Register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const struct max2175_rxmode eu_rx_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* EU modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) [MAX2175_EU_FM_1_2] = { MAX2175_BAND_FM, 98256000, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) [MAX2175_DAB_1_2] = { MAX2175_BAND_VHF, 182640000, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static const struct max2175_rxmode na_rx_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* NA modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [MAX2175_NA_FM_1_0] = { MAX2175_BAND_FM, 98255520, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [MAX2175_NA_FM_2_0] = { MAX2175_BAND_FM, 98255520, 6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * Preset values:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Based on Maxim MAX2175 Register Table revision: 130p10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static const u8 full_fm_eu_1p0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) 0x15, 0x04, 0xb8, 0xe3, 0x35, 0x18, 0x7c, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) 0x00, 0x7d, 0x40, 0x08, 0x70, 0x7a, 0x88, 0x91,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 0x61, 0x61, 0x61, 0x61, 0x5a, 0x0f, 0x34, 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 0x14, 0x88, 0x33, 0x02, 0x00, 0x09, 0x00, 0x65,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 0x9f, 0x2b, 0x80, 0x00, 0x95, 0x05, 0x2c, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 0x4a, 0x08, 0xa8, 0x0e, 0x0e, 0x2f, 0x7e, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5e, 0xa9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 0xae, 0xbb, 0x57, 0x18, 0x3b, 0x03, 0x3b, 0x64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 0x40, 0x60, 0x00, 0x2a, 0xbf, 0x3f, 0xff, 0x9f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 0xff, 0xfc, 0xef, 0x1c, 0x40, 0x00, 0x00, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x40, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 0x00, 0x47, 0x00, 0x00, 0x11, 0x3f, 0x22, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 0xf1, 0x00, 0x41, 0x03, 0xb0, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static const u8 full_fm_na_1p0[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 0x13, 0x08, 0x8d, 0xc0, 0x35, 0x18, 0x7d, 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 0x7d, 0x75, 0x40, 0x08, 0x70, 0x7a, 0x88, 0x91,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) 0x61, 0x61, 0x61, 0x61, 0x5c, 0x0f, 0x34, 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 0x14, 0x88, 0x33, 0x02, 0x00, 0x01, 0x00, 0x65,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 0x9f, 0x2b, 0x80, 0x00, 0x95, 0x05, 0x2c, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 0x4a, 0x08, 0xa8, 0x0e, 0x0e, 0xaf, 0x7e, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5e, 0xa9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) 0xae, 0xbb, 0x57, 0x18, 0x3b, 0x03, 0x3b, 0x64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) 0x40, 0x60, 0x00, 0x2a, 0xbf, 0x3f, 0xff, 0x9f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) 0xff, 0xfc, 0xef, 0x1c, 0x40, 0x00, 0x00, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x40, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 0x00, 0x35, 0x00, 0x00, 0x11, 0x3f, 0x22, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 0xf1, 0x00, 0x41, 0x03, 0xb0, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* DAB1.2 settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static const struct max2175_reg_map dab12_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { 0x01, 0x13 }, { 0x02, 0x0d }, { 0x03, 0x15 }, { 0x04, 0x55 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { 0x05, 0x0a }, { 0x06, 0xa0 }, { 0x07, 0x40 }, { 0x08, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { 0x09, 0x00 }, { 0x0a, 0x7d }, { 0x0b, 0x4a }, { 0x0c, 0x28 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { 0x0e, 0x43 }, { 0x0f, 0xb5 }, { 0x10, 0x31 }, { 0x11, 0x9e },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { 0x12, 0x68 }, { 0x13, 0x9e }, { 0x14, 0x68 }, { 0x15, 0x58 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { 0x16, 0x2f }, { 0x17, 0x3f }, { 0x18, 0x40 }, { 0x1a, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { 0x1b, 0xaa }, { 0x1c, 0x9a }, { 0x1d, 0x00 }, { 0x1e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x00 }, { 0x26, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { 0x27, 0x00 }, { 0x32, 0x08 }, { 0x33, 0xf8 }, { 0x36, 0x2d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { 0x37, 0x7e }, { 0x55, 0xaf }, { 0x56, 0x3f }, { 0x57, 0xf8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { 0x58, 0x99 }, { 0x76, 0x00 }, { 0x77, 0x00 }, { 0x78, 0x02 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { 0x79, 0x40 }, { 0x82, 0x00 }, { 0x83, 0x00 }, { 0x85, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { 0x86, 0x20 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* EU FM 1.2 settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static const struct max2175_reg_map fmeu1p2_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { 0x01, 0x15 }, { 0x02, 0x04 }, { 0x03, 0xb8 }, { 0x04, 0xe3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7c }, { 0x08, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { 0x09, 0x00 }, { 0x0a, 0x73 }, { 0x0b, 0x40 }, { 0x0c, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0x2f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { 0x58, 0x9f }, { 0x76, 0xac }, { 0x77, 0x40 }, { 0x78, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { 0x79, 0x00 }, { 0x82, 0x47 }, { 0x83, 0x00 }, { 0x85, 0x11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { 0x86, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* FM NA 1.0 settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct max2175_reg_map fmna1p0_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { 0x01, 0x13 }, { 0x02, 0x08 }, { 0x03, 0x8d }, { 0x04, 0xc0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7d }, { 0x08, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { 0x09, 0x7d }, { 0x0a, 0x75 }, { 0x0b, 0x40 }, { 0x0c, 0x08 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0xaf },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { 0x58, 0x9f }, { 0x76, 0xa6 }, { 0x77, 0x40 }, { 0x78, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { 0x79, 0x00 }, { 0x82, 0x35 }, { 0x83, 0x00 }, { 0x85, 0x11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { 0x86, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* FM NA 2.0 settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct max2175_reg_map fmna2p0_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { 0x01, 0x13 }, { 0x02, 0x08 }, { 0x03, 0x8d }, { 0x04, 0xc0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { 0x05, 0x35 }, { 0x06, 0x18 }, { 0x07, 0x7c }, { 0x08, 0x54 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { 0x09, 0xa7 }, { 0x0a, 0x55 }, { 0x0b, 0x42 }, { 0x0c, 0x48 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { 0x0e, 0x7a }, { 0x0f, 0x88 }, { 0x10, 0x91 }, { 0x11, 0x61 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { 0x12, 0x61 }, { 0x13, 0x61 }, { 0x14, 0x61 }, { 0x15, 0x5c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { 0x16, 0x0f }, { 0x17, 0x34 }, { 0x18, 0x1c }, { 0x1a, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { 0x1b, 0x33 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x1e, 0x01 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { 0x23, 0x80 }, { 0x24, 0x00 }, { 0x25, 0x95 }, { 0x26, 0x05 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { 0x27, 0x2c }, { 0x32, 0x08 }, { 0x33, 0xa8 }, { 0x36, 0xaf },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { 0x37, 0x7e }, { 0x55, 0xbf }, { 0x56, 0x3f }, { 0x57, 0xff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { 0x58, 0x9f }, { 0x76, 0xac }, { 0x77, 0xc0 }, { 0x78, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { 0x79, 0x00 }, { 0x82, 0x6b }, { 0x83, 0x00 }, { 0x85, 0x11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { 0x86, 0x3f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static const u16 ch_coeff_dab1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 0x001c, 0x0007, 0xffcd, 0x0056, 0xffa4, 0x0033, 0x0027, 0xff61,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 0x010e, 0xfec0, 0x0106, 0xffb8, 0xff1c, 0x023c, 0xfcb2, 0x039b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 0xfd4e, 0x0055, 0x036a, 0xf7de, 0x0d21, 0xee72, 0x1499, 0x6a51,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static const u16 ch_coeff_fmeu[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 0x0000, 0xffff, 0x0001, 0x0002, 0xfffa, 0xffff, 0x0015, 0xffec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 0xffde, 0x0054, 0xfff9, 0xff52, 0x00b8, 0x00a2, 0xfe0a, 0x00af,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 0x02e3, 0xfc14, 0xfe89, 0x089d, 0xfa2e, 0xf30f, 0x25be, 0x4eb6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static const u16 eq_coeff_fmeu1_ra02_m6db[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 0x0040, 0xffc6, 0xfffa, 0x002c, 0x000d, 0xff90, 0x0037, 0x006e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 0xffc0, 0xff5b, 0x006a, 0x00f0, 0xff57, 0xfe94, 0x0112, 0x0252,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 0xfe0c, 0xfc6a, 0x0385, 0x0553, 0xfa49, 0xf789, 0x0b91, 0x1a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static const u16 ch_coeff_fmna[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 0x0001, 0x0003, 0xfffe, 0xfff4, 0x0000, 0x001f, 0x000c, 0xffbc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 0xffd3, 0x007d, 0x0075, 0xff33, 0xff01, 0x0131, 0x01ef, 0xfe60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 0xfc7a, 0x020e, 0x0656, 0xfd94, 0xf395, 0x02ab, 0x2857, 0x3d3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static const u16 eq_coeff_fmna1_ra02_m6db[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 0xfff1, 0xffe1, 0xffef, 0x000e, 0x0030, 0x002f, 0xfff6, 0xffa7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 0xff9d, 0x000a, 0x00a2, 0x00b5, 0xffea, 0xfed9, 0xfec5, 0x003d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 0x0217, 0x021b, 0xff5a, 0xfc2b, 0xfcbd, 0x02c4, 0x0ac3, 0x0e85,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static const u8 adc_presets[2][23] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 0x83, 0x00, 0xcf, 0xb4, 0x0f, 0x2c, 0x0c, 0x49,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 0x00, 0x00, 0x00, 0x8c, 0x02, 0x02, 0x00, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 0xec, 0x82, 0x4b, 0xcc, 0x01, 0x88, 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 0x83, 0x00, 0xcf, 0xb4, 0x0f, 0x2c, 0x0c, 0x49,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 0x00, 0x00, 0x00, 0x8c, 0x02, 0x20, 0x33, 0x8c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 0x57, 0xd7, 0x59, 0xb7, 0x65, 0x0e, 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* Tuner bands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static const struct v4l2_frequency_band eu_bands_rf = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .tuner = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .type = V4L2_TUNER_RF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .rangelow = 65000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .rangehigh = 240000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static const struct v4l2_frequency_band na_bands_rf = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .tuner = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .type = V4L2_TUNER_RF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .rangelow = 65000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .rangehigh = 108000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* Regmap settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static const struct regmap_range max2175_regmap_volatile_range[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) regmap_reg_range(0x30, 0x35),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) regmap_reg_range(0x3a, 0x45),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) regmap_reg_range(0x59, 0x5e),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) regmap_reg_range(0x73, 0x75),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static const struct regmap_access_table max2175_volatile_regs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .yes_ranges = max2175_regmap_volatile_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .n_yes_ranges = ARRAY_SIZE(max2175_regmap_volatile_range),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static const struct reg_default max2175_reg_defaults[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) { 0x00, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static const struct regmap_config max2175_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .reg_defaults = max2175_reg_defaults,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .num_reg_defaults = ARRAY_SIZE(max2175_reg_defaults),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .volatile_table = &max2175_volatile_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .cache_type = REGCACHE_FLAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct max2175 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct v4l2_subdev sd; /* Sub-device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct i2c_client *client; /* I2C client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct v4l2_ctrl_handler ctrl_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct v4l2_ctrl *lna_gain; /* LNA gain value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct v4l2_ctrl *if_gain; /* I/F gain value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct v4l2_ctrl *pll_lock; /* PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct v4l2_ctrl *i2s_en; /* I2S output enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct v4l2_ctrl *hsls; /* High-side/Low-side polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct v4l2_ctrl *rx_mode; /* Receive mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* Regmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Cached configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u32 freq; /* Tuned freq In Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) const struct max2175_rxmode *rx_modes; /* EU or NA modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) const struct v4l2_frequency_band *bands_rf; /* EU or NA bands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* Device settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) unsigned long xtal_freq; /* Ref Oscillator freq in Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u32 decim_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) bool master; /* Master/Slave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) bool am_hiz; /* AM Hi-Z filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* ROM values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u8 rom_bbf_bw_am;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u8 rom_bbf_bw_fm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) u8 rom_bbf_bw_dab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* Driver private variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) bool mode_resolved; /* Flag to sanity check settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static inline struct max2175 *max2175_from_sd(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return container_of(sd, struct max2175, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static inline struct max2175 *max2175_from_ctrl_hdl(struct v4l2_ctrl_handler *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return container_of(h, struct max2175, ctrl_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* Get bitval of a given val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static inline u8 max2175_get_bitval(u8 val, u8 msb, u8 lsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return (val & GENMASK(msb, lsb)) >> lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Read/Write bit(s) on top of regmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int max2175_read(struct max2175 *ctx, u8 idx, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) u32 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = regmap_read(ctx->regmap, idx, ®val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) mxm_err(ctx, "read ret(%d): idx 0x%02x\n", ret, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *val = regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int max2175_write(struct max2175 *ctx, u8 idx, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ret = regmap_write(ctx->regmap, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) mxm_err(ctx, "write ret(%d): idx 0x%02x val 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static u8 max2175_read_bits(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (max2175_read(ctx, idx, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return max2175_get_bitval(val, msb, lsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static int max2175_write_bits(struct max2175 *ctx, u8 idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) u8 msb, u8 lsb, u8 newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int ret = regmap_update_bits(ctx->regmap, idx, GENMASK(msb, lsb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) newval << lsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mxm_err(ctx, "wbits ret(%d): idx 0x%02x\n", ret, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int max2175_write_bit(struct max2175 *ctx, u8 idx, u8 bit, u8 newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return max2175_write_bits(ctx, idx, bit, bit, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* Checks expected pattern every msec until timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int max2175_poll_timeout(struct max2175 *ctx, u8 idx, u8 msb, u8 lsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u8 exp_bitval, u32 timeout_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return regmap_read_poll_timeout(ctx->regmap, idx, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) (max2175_get_bitval(val, msb, lsb) == exp_bitval),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 1000, timeout_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int max2175_poll_csm_ready(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = max2175_poll_timeout(ctx, 69, 1, 1, 0, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) mxm_err(ctx, "csm not ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) #define MAX2175_IS_BAND_AM(ctx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) (max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_AM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) #define MAX2175_IS_BAND_VHF(ctx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) (max2175_read_bits(ctx, 5, 1, 0) == MAX2175_BAND_VHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) #define MAX2175_IS_FM_MODE(ctx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) (max2175_read_bits(ctx, 12, 5, 4) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) #define MAX2175_IS_FMHD_MODE(ctx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) (max2175_read_bits(ctx, 12, 5, 4) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) #define MAX2175_IS_DAB_MODE(ctx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) (max2175_read_bits(ctx, 12, 5, 4) == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static int max2175_band_from_freq(u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (freq >= 144000 && freq <= 26100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return MAX2175_BAND_AM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) else if (freq >= 65000000 && freq <= 108000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return MAX2175_BAND_FM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return MAX2175_BAND_VHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static void max2175_i2s_enable(struct max2175 *ctx, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* Stuff bits are zeroed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) max2175_write_bits(ctx, 104, 3, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* Keep SCK alive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) max2175_write_bits(ctx, 104, 3, 0, 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mxm_dbg(ctx, "i2s %sabled\n", enable ? "en" : "dis");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static void max2175_set_filter_coeffs(struct max2175 *ctx, u8 m_sel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) u8 bank, const u16 *coeffs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u8 coeff_addr, upper_address = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) mxm_dbg(ctx, "set_filter_coeffs: m_sel %d bank %d\n", m_sel, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) max2175_write_bits(ctx, 114, 5, 4, m_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (m_sel == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) upper_address = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) for (i = 0; i < upper_address; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) coeff_addr = i + bank * 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) max2175_write(ctx, 115, coeffs[i] >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) max2175_write(ctx, 116, coeffs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) max2175_write(ctx, 117, coeff_addr | 1 << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) max2175_write_bit(ctx, 117, 7, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static void max2175_load_fmeu_1p2(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) for (i = 0; i < ARRAY_SIZE(fmeu1p2_map); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) max2175_write(ctx, fmeu1p2_map[i].idx, fmeu1p2_map[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ctx->decim_ratio = 36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* Load the Channel Filter Coefficients into channel filter bank #2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0, ch_coeff_fmeu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) eq_coeff_fmeu1_ra02_m6db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static void max2175_load_dab_1p2(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) for (i = 0; i < ARRAY_SIZE(dab12_map); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) max2175_write(ctx, dab12_map[i].idx, dab12_map[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ctx->decim_ratio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Load the Channel Filter Coefficients into channel filter bank #2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 2, ch_coeff_dab1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static void max2175_load_fmna_1p0(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) for (i = 0; i < ARRAY_SIZE(fmna1p0_map); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) max2175_write(ctx, fmna1p0_map[i].idx, fmna1p0_map[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static void max2175_load_fmna_2p0(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) for (i = 0; i < ARRAY_SIZE(fmna2p0_map); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) max2175_write(ctx, fmna2p0_map[i].idx, fmna2p0_map[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static void max2175_set_bbfilter(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (MAX2175_IS_BAND_AM(ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_am);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) mxm_dbg(ctx, "set_bbfilter AM: rom %d\n", ctx->rom_bbf_bw_am);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) } else if (MAX2175_IS_DAB_MODE(ctx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_dab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) mxm_dbg(ctx, "set_bbfilter DAB: rom %d\n", ctx->rom_bbf_bw_dab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) max2175_write_bits(ctx, 12, 3, 0, ctx->rom_bbf_bw_fm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) mxm_dbg(ctx, "set_bbfilter FM: rom %d\n", ctx->rom_bbf_bw_fm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int max2175_set_csm_mode(struct max2175 *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) enum max2175_csm_mode new_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) int ret = max2175_poll_csm_ready(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) max2175_write_bits(ctx, 0, 2, 0, new_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) mxm_dbg(ctx, "set csm new mode %d\n", new_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* Wait for a fixed settle down time depending on new mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) switch (new_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case MAX2175_PRESET_TUNE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) usleep_range(51100, 51500); /* 51.1ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * Other mode switches need different sleep values depending on band &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return max2175_poll_csm_ready(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int max2175_csm_action(struct max2175 *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) enum max2175_csm_mode action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mxm_dbg(ctx, "csm_action: %d\n", action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* Other actions can be added in future when needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) ret = max2175_set_csm_mode(ctx, MAX2175_LOAD_TO_BUFFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return max2175_set_csm_mode(ctx, MAX2175_PRESET_TUNE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int max2175_set_lo_freq(struct max2175 *ctx, u32 lo_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u8 lo_mult, loband_bits = 0, vcodiv_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u32 int_desired, frac_desired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) enum max2175_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) band = max2175_read_bits(ctx, 5, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) switch (band) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case MAX2175_BAND_AM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) lo_mult = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case MAX2175_BAND_FM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (lo_freq <= 74700000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) lo_mult = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) } else if (lo_freq > 74700000 && lo_freq <= 110000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) loband_bits = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) lo_mult = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) loband_bits = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) vcodiv_bits = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) lo_mult = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case MAX2175_BAND_VHF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (lo_freq <= 210000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) vcodiv_bits = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) vcodiv_bits = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) loband_bits = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) lo_mult = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) loband_bits = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) vcodiv_bits = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) lo_mult = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (band == MAX2175_BAND_L)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) lo_freq /= lo_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) lo_freq *= lo_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int_desired = lo_freq / ctx->xtal_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) frac_desired = div64_ul((u64)(lo_freq % ctx->xtal_freq) << 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ctx->xtal_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* Check CSM is not busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ret = max2175_poll_csm_ready(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) mxm_dbg(ctx, "lo_mult %u int %u frac %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) lo_mult, int_desired, frac_desired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* Write the calculated values to the appropriate registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) max2175_write(ctx, 1, int_desired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) max2175_write_bits(ctx, 2, 3, 0, (frac_desired >> 16) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) max2175_write(ctx, 3, frac_desired >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) max2175_write(ctx, 4, frac_desired);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) max2175_write_bits(ctx, 5, 3, 2, loband_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) max2175_write_bits(ctx, 6, 7, 6, vcodiv_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * Helper similar to DIV_ROUND_CLOSEST but an inline function that accepts s64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * dividend and s32 divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static inline s64 max2175_round_closest(s64 dividend, s32 divisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return div_s64(dividend + divisor / 2, divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return div_s64(dividend - divisor / 2, divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) static int max2175_set_nco_freq(struct max2175 *ctx, s32 nco_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) s32 clock_rate = ctx->xtal_freq / ctx->decim_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) u32 nco_reg, abs_nco_freq = abs(nco_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) s64 nco_val_desired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (abs_nco_freq < clock_rate / 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) nco_val_desired = 2 * nco_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) nco_val_desired = 2LL * (clock_rate - abs_nco_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (nco_freq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) nco_val_desired = -nco_val_desired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) nco_reg = max2175_round_closest(nco_val_desired << 20, clock_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (nco_freq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) nco_reg += 0x200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* Check CSM is not busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = max2175_poll_csm_ready(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mxm_dbg(ctx, "freq %d desired %lld reg %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) nco_freq, nco_val_desired, nco_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* Write the calculated values to the appropriate registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) max2175_write_bits(ctx, 7, 4, 0, (nco_reg >> 16) & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) max2175_write(ctx, 8, nco_reg >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) max2175_write(ctx, 9, nco_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int max2175_set_rf_freq_non_am_bands(struct max2175 *ctx, u64 freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) u32 lo_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) s64 adj_freq, low_if_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) mxm_dbg(ctx, "rf_freq: non AM bands\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (MAX2175_IS_FM_MODE(ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) low_if_freq = 128000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) else if (MAX2175_IS_FMHD_MODE(ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) low_if_freq = 228000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return max2175_set_lo_freq(ctx, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (MAX2175_IS_BAND_VHF(ctx) == (lo_pos == MAX2175_LO_ABOVE_DESIRED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) adj_freq = freq + low_if_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) adj_freq = freq - low_if_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ret = max2175_set_lo_freq(ctx, adj_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return max2175_set_nco_freq(ctx, -low_if_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static int max2175_set_rf_freq(struct max2175 *ctx, u64 freq, u32 lo_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (MAX2175_IS_BAND_AM(ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ret = max2175_set_nco_freq(ctx, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ret = max2175_set_rf_freq_non_am_bands(ctx, freq, lo_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) mxm_dbg(ctx, "set_rf_freq: ret %d freq %llu\n", ret, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static int max2175_tune_rf_freq(struct max2175 *ctx, u64 freq, u32 hsls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = max2175_set_rf_freq(ctx, freq, hsls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ret = max2175_csm_action(ctx, MAX2175_BUFFER_PLUS_PRESET_TUNE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) mxm_dbg(ctx, "tune_rf_freq: old %u new %llu\n", ctx->freq, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ctx->freq = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static void max2175_set_hsls(struct max2175 *ctx, u32 lo_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) mxm_dbg(ctx, "set_hsls: lo_pos %u\n", lo_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if ((lo_pos == MAX2175_LO_BELOW_DESIRED) == MAX2175_IS_BAND_VHF(ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) max2175_write_bit(ctx, 5, 4, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) max2175_write_bit(ctx, 5, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static void max2175_set_eu_rx_mode(struct max2175 *ctx, u32 rx_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) switch (rx_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) case MAX2175_EU_FM_1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) max2175_load_fmeu_1p2(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) case MAX2175_DAB_1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) max2175_load_dab_1p2(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* Master is the default setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (!ctx->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) max2175_write_bit(ctx, 30, 7, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static void max2175_set_na_rx_mode(struct max2175 *ctx, u32 rx_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) switch (rx_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) case MAX2175_NA_FM_1_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) max2175_load_fmna_1p0(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) case MAX2175_NA_FM_2_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) max2175_load_fmna_2p0(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* Master is the default setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (!ctx->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) max2175_write_bit(ctx, 30, 7, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ctx->decim_ratio = 27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Load the Channel Filter Coefficients into channel filter bank #2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0, ch_coeff_fmna);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) eq_coeff_fmna1_ra02_m6db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static int max2175_set_rx_mode(struct max2175 *ctx, u32 rx_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) mxm_dbg(ctx, "set_rx_mode: %u am_hiz %u\n", rx_mode, ctx->am_hiz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) max2175_set_eu_rx_mode(ctx, rx_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) max2175_set_na_rx_mode(ctx, rx_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (ctx->am_hiz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) mxm_dbg(ctx, "setting AM HiZ related config\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) max2175_write_bit(ctx, 50, 5, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) max2175_write_bit(ctx, 90, 7, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) max2175_write_bits(ctx, 73, 1, 0, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) max2175_write_bits(ctx, 80, 5, 0, 33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* Load BB filter trim values saved in ROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) max2175_set_bbfilter(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /* Set HSLS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) max2175_set_hsls(ctx, ctx->hsls->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* Use i2s enable settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) max2175_i2s_enable(ctx, ctx->i2s_en->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ctx->mode_resolved = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int max2175_rx_mode_from_freq(struct max2175 *ctx, u32 freq, u32 *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int band = max2175_band_from_freq(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* Pick the first match always */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) for (i = 0; i <= ctx->rx_mode->maximum; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (ctx->rx_modes[i].band == band) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *mode = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) mxm_dbg(ctx, "rx_mode_from_freq: freq %u mode %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) freq, *mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static bool max2175_freq_rx_mode_valid(struct max2175 *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) u32 mode, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) int band = max2175_band_from_freq(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return (ctx->rx_modes[mode].band == band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static void max2175_load_adc_presets(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) for (i = 0; i < ARRAY_SIZE(adc_presets); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) for (j = 0; j < ARRAY_SIZE(adc_presets[0]); j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) max2175_write(ctx, 146 + j + i * 55, adc_presets[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static int max2175_init_power_manager(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* Execute on-chip power-up/calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) max2175_write_bit(ctx, 99, 2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) usleep_range(1000, 1500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) max2175_write_bit(ctx, 99, 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* Wait for the power manager to finish. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ret = max2175_poll_timeout(ctx, 69, 7, 7, 1, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) mxm_err(ctx, "init pm failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static int max2175_recalibrate_adc(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /* ADC Re-calibration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) max2175_write(ctx, 150, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) max2175_write(ctx, 205, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) max2175_write(ctx, 147, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) max2175_write(ctx, 147, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) max2175_write(ctx, 202, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) max2175_write(ctx, 202, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ret = max2175_poll_timeout(ctx, 69, 4, 3, 3, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) mxm_err(ctx, "adc recalibration failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static u8 max2175_read_rom(struct max2175 *ctx, u8 row)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) u8 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) max2175_write_bit(ctx, 56, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) max2175_write_bits(ctx, 56, 3, 0, row);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) usleep_range(2000, 2500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) max2175_read(ctx, 58, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) max2175_write_bits(ctx, 56, 3, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) mxm_dbg(ctx, "read_rom: row %d data 0x%02x\n", row, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static void max2175_load_from_rom(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) u8 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) data = max2175_read_rom(ctx, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) ctx->rom_bbf_bw_am = data & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) max2175_write_bits(ctx, 81, 3, 0, data >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) data = max2175_read_rom(ctx, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ctx->rom_bbf_bw_fm = data & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) ctx->rom_bbf_bw_dab = data >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) data = max2175_read_rom(ctx, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) max2175_write_bits(ctx, 82, 4, 0, data & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) max2175_write_bits(ctx, 82, 7, 5, data >> 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) data = max2175_read_rom(ctx, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (ctx->am_hiz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) data &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) data |= (max2175_read_rom(ctx, 7) & 0x40) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) data |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) data = (data & 0xf0) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) data |= (max2175_read_rom(ctx, 7) & 0x80) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) data |= 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) max2175_write_bits(ctx, 80, 5, 0, data + 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) data = max2175_read_rom(ctx, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) max2175_write_bits(ctx, 81, 7, 6, data >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) static void max2175_load_full_fm_eu_1p0(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) for (i = 0; i < ARRAY_SIZE(full_fm_eu_1p0); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) max2175_write(ctx, i + 1, full_fm_eu_1p0[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) usleep_range(5000, 5500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) ctx->decim_ratio = 36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static void max2175_load_full_fm_na_1p0(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) for (i = 0; i < ARRAY_SIZE(full_fm_na_1p0); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) max2175_write(ctx, i + 1, full_fm_na_1p0[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) usleep_range(5000, 5500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) ctx->decim_ratio = 27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static int max2175_core_init(struct max2175 *ctx, u32 refout_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* MAX2175 uses 36.864MHz clock for EU & 40.154MHz for NA region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) max2175_load_full_fm_eu_1p0(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) max2175_load_full_fm_na_1p0(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /* The default settings assume master */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (!ctx->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) max2175_write_bit(ctx, 30, 7, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) mxm_dbg(ctx, "refout_bits %u\n", refout_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /* Set REFOUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) max2175_write_bits(ctx, 56, 7, 5, refout_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* ADC Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) max2175_write_bit(ctx, 99, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) usleep_range(1000, 1500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) max2175_write_bit(ctx, 99, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) /* Load ADC preset values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) max2175_load_adc_presets(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /* Initialize the power management state machine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) ret = max2175_init_power_manager(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* Recalibrate ADC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ret = max2175_recalibrate_adc(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /* Load ROM values to appropriate registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) max2175_load_from_rom(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* Load FIR coefficients into bank 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) ch_coeff_fmeu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) eq_coeff_fmeu1_ra02_m6db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* Load FIR coefficients into bank 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) max2175_set_filter_coeffs(ctx, MAX2175_CH_MSEL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) ch_coeff_fmna);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) max2175_set_filter_coeffs(ctx, MAX2175_EQ_MSEL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) eq_coeff_fmna1_ra02_m6db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) mxm_dbg(ctx, "core initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) static void max2175_s_ctrl_rx_mode(struct max2175 *ctx, u32 rx_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* Load mode. Range check already done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) max2175_set_rx_mode(ctx, rx_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) mxm_dbg(ctx, "s_ctrl_rx_mode: %u curr freq %u\n", rx_mode, ctx->freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* Check if current freq valid for mode & update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (max2175_freq_rx_mode_valid(ctx, rx_mode, ctx->freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) max2175_tune_rf_freq(ctx, ctx->freq, ctx->hsls->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* Use default freq of mode if current freq is not valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) max2175_tune_rf_freq(ctx, ctx->rx_modes[rx_mode].freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ctx->hsls->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static int max2175_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct max2175 *ctx = max2175_from_ctrl_hdl(ctrl->handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) mxm_dbg(ctx, "s_ctrl: id 0x%x, val %u\n", ctrl->id, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) case V4L2_CID_MAX2175_I2S_ENABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) max2175_i2s_enable(ctx, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) case V4L2_CID_MAX2175_HSLS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) max2175_set_hsls(ctx, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) case V4L2_CID_MAX2175_RX_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) max2175_s_ctrl_rx_mode(ctx, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static u32 max2175_get_lna_gain(struct max2175 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) enum max2175_band band = max2175_read_bits(ctx, 5, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) switch (band) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case MAX2175_BAND_AM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return max2175_read_bits(ctx, 51, 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) case MAX2175_BAND_FM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return max2175_read_bits(ctx, 50, 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) case MAX2175_BAND_VHF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return max2175_read_bits(ctx, 52, 5, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static int max2175_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct max2175 *ctx = max2175_from_ctrl_hdl(ctrl->handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) case V4L2_CID_RF_TUNER_LNA_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) ctrl->val = max2175_get_lna_gain(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) case V4L2_CID_RF_TUNER_IF_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) ctrl->val = max2175_read_bits(ctx, 49, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) case V4L2_CID_RF_TUNER_PLL_LOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ctrl->val = (max2175_read_bits(ctx, 60, 7, 6) == 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) static int max2175_set_freq_and_mode(struct max2175 *ctx, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) u32 rx_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* Get band from frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) ret = max2175_rx_mode_from_freq(ctx, freq, &rx_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) mxm_dbg(ctx, "set_freq_and_mode: freq %u rx_mode %d\n", freq, rx_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /* Load mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) max2175_set_rx_mode(ctx, rx_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) ctx->rx_mode->cur.val = rx_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* Tune to the new freq given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return max2175_tune_rf_freq(ctx, freq, ctx->hsls->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) static int max2175_s_frequency(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) const struct v4l2_frequency *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct max2175 *ctx = max2175_from_sd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) mxm_dbg(ctx, "s_freq: new %u curr %u, mode_resolved %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) vf->frequency, ctx->freq, ctx->mode_resolved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (vf->tuner != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) freq = clamp(vf->frequency, ctx->bands_rf->rangelow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) ctx->bands_rf->rangehigh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* Check new freq valid for rx_mode if already resolved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (ctx->mode_resolved &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) max2175_freq_rx_mode_valid(ctx, ctx->rx_mode->cur.val, freq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) ret = max2175_tune_rf_freq(ctx, freq, ctx->hsls->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* Find default rx_mode for freq and tune to it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ret = max2175_set_freq_and_mode(ctx, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) mxm_dbg(ctx, "s_freq: ret %d curr %u mode_resolved %d mode %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) ret, ctx->freq, ctx->mode_resolved, ctx->rx_mode->cur.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) static int max2175_g_frequency(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct v4l2_frequency *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) struct max2175 *ctx = max2175_from_sd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (vf->tuner != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* RF freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) vf->type = V4L2_TUNER_RF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) vf->frequency = ctx->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static int max2175_enum_freq_bands(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) struct v4l2_frequency_band *band)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct max2175 *ctx = max2175_from_sd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (band->tuner != 0 || band->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) *band = *ctx->bands_rf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) static int max2175_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct max2175 *ctx = max2175_from_sd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (vt->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) strscpy(vt->name, "RF", sizeof(vt->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) vt->type = V4L2_TUNER_RF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) vt->rangelow = ctx->bands_rf->rangelow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) vt->rangehigh = ctx->bands_rf->rangehigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static int max2175_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) /* Check tuner index is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (vt->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) static const struct v4l2_subdev_tuner_ops max2175_tuner_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) .s_frequency = max2175_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .g_frequency = max2175_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .enum_freq_bands = max2175_enum_freq_bands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) .g_tuner = max2175_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .s_tuner = max2175_s_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static const struct v4l2_subdev_ops max2175_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .tuner = &max2175_tuner_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) static const struct v4l2_ctrl_ops max2175_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) .s_ctrl = max2175_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) .g_volatile_ctrl = max2175_g_volatile_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) * I2S output enable/disable configuration. This is a private control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) * Refer to Documentation/userspace-api/media/drivers/max2175.rst for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static const struct v4l2_ctrl_config max2175_i2s_en = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) .ops = &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) .id = V4L2_CID_MAX2175_I2S_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) .name = "I2S Enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .type = V4L2_CTRL_TYPE_BOOLEAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) .max = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) .def = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) .is_private = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) * HSLS value control LO freq adjacent location configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * Refer to Documentation/userspace-api/media/drivers/max2175.rst for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static const struct v4l2_ctrl_config max2175_hsls = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .ops = &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) .id = V4L2_CID_MAX2175_HSLS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .name = "HSLS Above/Below Desired",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) .type = V4L2_CTRL_TYPE_BOOLEAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) .max = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) .def = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * Rx modes below are a set of preset configurations that decides the tuner's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * sck and sample rate of transmission. They are separate for EU & NA regions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) * Refer to Documentation/userspace-api/media/drivers/max2175.rst for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) static const char * const max2175_ctrl_eu_rx_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) [MAX2175_EU_FM_1_2] = "EU FM 1.2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) [MAX2175_DAB_1_2] = "DAB 1.2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) static const char * const max2175_ctrl_na_rx_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) [MAX2175_NA_FM_1_0] = "NA FM 1.0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) [MAX2175_NA_FM_2_0] = "NA FM 2.0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) static const struct v4l2_ctrl_config max2175_eu_rx_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) .ops = &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) .id = V4L2_CID_MAX2175_RX_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) .name = "RX Mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) .type = V4L2_CTRL_TYPE_MENU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .max = ARRAY_SIZE(max2175_ctrl_eu_rx_modes) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .qmenu = max2175_ctrl_eu_rx_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) static const struct v4l2_ctrl_config max2175_na_rx_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) .ops = &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) .id = V4L2_CID_MAX2175_RX_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .name = "RX Mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .type = V4L2_CTRL_TYPE_MENU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) .max = ARRAY_SIZE(max2175_ctrl_na_rx_modes) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .qmenu = max2175_ctrl_na_rx_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static int max2175_refout_load_to_bits(struct i2c_client *client, u32 load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) u32 *bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (load <= 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) *bits = load / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) else if (load >= 60 && load <= 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) *bits = load / 10 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static int max2175_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) bool master = true, am_hiz = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) u32 refout_load, refout_bits = 0; /* REFOUT disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) struct v4l2_ctrl_handler *hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct fwnode_handle *fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct max2175 *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) /* Parse DT properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) np = of_parse_phandle(client->dev.of_node, "maxim,master", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) master = false; /* Slave tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) fwnode = of_fwnode_handle(client->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (fwnode_property_present(fwnode, "maxim,am-hiz-filter"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) am_hiz = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (!fwnode_property_read_u32(fwnode, "maxim,refout-load",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) &refout_load)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ret = max2175_refout_load_to_bits(client, refout_load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) &refout_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) dev_err(&client->dev, "invalid refout_load %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) refout_load);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) clk = devm_clk_get(&client->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) ret = PTR_ERR(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) dev_err(&client->dev, "cannot get clock %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) regmap = devm_regmap_init_i2c(client, &max2175_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) ret = PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) dev_err(&client->dev, "regmap init failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) /* Alloc tuner context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) ctx = devm_kzalloc(&client->dev, sizeof(*ctx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (ctx == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) sd = &ctx->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) ctx->master = master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) ctx->am_hiz = am_hiz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) ctx->mode_resolved = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) ctx->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) ctx->xtal_freq = clk_get_rate(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) dev_info(&client->dev, "xtal freq %luHz\n", ctx->xtal_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) v4l2_i2c_subdev_init(sd, client, &max2175_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) ctx->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /* Controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) hdl = &ctx->ctrl_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) ret = v4l2_ctrl_handler_init(hdl, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) ctx->lna_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) V4L2_CID_RF_TUNER_LNA_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 0, 63, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) ctx->lna_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) V4L2_CTRL_FLAG_READ_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) ctx->if_gain = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) V4L2_CID_RF_TUNER_IF_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 0, 31, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) ctx->if_gain->flags |= (V4L2_CTRL_FLAG_VOLATILE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) V4L2_CTRL_FLAG_READ_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) ctx->pll_lock = v4l2_ctrl_new_std(hdl, &max2175_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) V4L2_CID_RF_TUNER_PLL_LOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) ctx->pll_lock->flags |= (V4L2_CTRL_FLAG_VOLATILE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) V4L2_CTRL_FLAG_READ_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ctx->i2s_en = v4l2_ctrl_new_custom(hdl, &max2175_i2s_en, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) ctx->hsls = v4l2_ctrl_new_custom(hdl, &max2175_hsls, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (ctx->xtal_freq == MAX2175_EU_XTAL_FREQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) &max2175_eu_rx_mode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) ctx->rx_modes = eu_rx_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ctx->bands_rf = &eu_bands_rf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) ctx->rx_mode = v4l2_ctrl_new_custom(hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) &max2175_na_rx_mode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) ctx->rx_modes = na_rx_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) ctx->bands_rf = &na_bands_rf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) ctx->sd.ctrl_handler = &ctx->ctrl_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* Set the defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) ctx->freq = ctx->bands_rf->rangelow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) /* Register subdev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ret = v4l2_async_register_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) dev_err(&client->dev, "register subdev failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) goto err_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) /* Initialize device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) ret = max2175_core_init(ctx, refout_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) ret = v4l2_ctrl_handler_setup(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) err_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) err_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) static int max2175_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) struct max2175 *ctx = max2175_from_sd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) static const struct i2c_device_id max2175_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) { DRIVER_NAME, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) MODULE_DEVICE_TABLE(i2c, max2175_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static const struct of_device_id max2175_of_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) { .compatible = "maxim,max2175", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) MODULE_DEVICE_TABLE(of, max2175_of_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) static struct i2c_driver max2175_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) .of_match_table = max2175_of_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) .probe_new = max2175_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) .remove = max2175_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) .id_table = max2175_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) module_i2c_driver(max2175_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) MODULE_DESCRIPTION("Maxim MAX2175 RF to Bits tuner driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) MODULE_AUTHOR("Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>");