Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] media: i2c: max2175: Add MAX2175 support

This patch adds driver support for the MAX2175 chip. This is Maxim
Integrated's RF to Bits tuner front end chip designed for software-defined
radio solutions. This driver exposes the tuner as a sub-device instance
with standard and custom controls to configure the device.

Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
Signed-off-by: Hans Verkuil <hansverk@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Ramesh Shanmugasundaram and committed by
Mauro Carvalho Chehab
b47b79d8 a45509c0

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