root/drivers/media/dvb-frontends/or51211.c
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *    Support for OR51211 (pcHDTV HD-2000) - VSB
 *
 *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
 *
 *    Based on code from Jack Kelliher (kelliher@xmission.com)
 *                           Copyright (C) 2002 & pcHDTV, inc.
*/

#define pr_fmt(fmt)     KBUILD_MODNAME ": %s: " fmt, __func__

/*
 * This driver needs external firmware. Please use the command
 * "<kerneldir>/scripts/get_dvb_firmware or51211" to
 * download/extract it, and then copy it to /usr/lib/hotplug/firmware
 * or /lib/firmware (depending on configuration of firmware hotplug).
 */
#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/byteorder.h>

#include <linux/int_log.h>
#include <media/dvb_frontend.h>
#include "or51211.h"

static int debug;
#define dprintk(args...) \
        do { if (debug) pr_debug(args); } while (0)

static u8 run_buf[] = {0x7f,0x01};
static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC

struct or51211_state {

        struct i2c_adapter* i2c;

        /* Configuration settings */
        const struct or51211_config* config;

        struct dvb_frontend frontend;
        struct bt878* bt;

        /* Demodulator private data */
        u8 initialized:1;
        u32 snr; /* Result of last SNR calculation */

        /* Tuner private data */
        u32 current_frequency;
};

static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
                           int len)
{
        int err;
        struct i2c_msg msg;
        msg.addr        = reg;
        msg.flags       = 0;
        msg.len         = len;
        msg.buf         = (u8 *)buf;

        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                pr_warn("error (addr %02x, err == %i)\n", reg, err);
                return -EREMOTEIO;
        }

        return 0;
}

static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len)
{
        int err;
        struct i2c_msg msg;
        msg.addr        = reg;
        msg.flags       = I2C_M_RD;
        msg.len         = len;
        msg.buf         = buf;

        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
                pr_warn("error (addr %02x, err == %i)\n", reg, err);
                return -EREMOTEIO;
        }

        return 0;
}

static int or51211_load_firmware (struct dvb_frontend* fe,
                                  const struct firmware *fw)
{
        struct or51211_state* state = fe->demodulator_priv;
        u8 tudata[585];
        int i;

        dprintk("Firmware is %zu bytes\n", fw->size);

        /* Get eprom data */
        tudata[0] = 17;
        if (i2c_writebytes(state,0x50,tudata,1)) {
                pr_warn("error eprom addr\n");
                return -1;
        }
        if (i2c_readbytes(state,0x50,&tudata[145],192)) {
                pr_warn("error eprom\n");
                return -1;
        }

        /* Create firmware buffer */
        for (i = 0; i < 145; i++)
                tudata[i] = fw->data[i];

        for (i = 0; i < 248; i++)
                tudata[i+337] = fw->data[145+i];

        state->config->reset(fe);

        if (i2c_writebytes(state,state->config->demod_address,tudata,585)) {
                pr_warn("error 1\n");
                return -1;
        }
        msleep(1);

        if (i2c_writebytes(state,state->config->demod_address,
                           &fw->data[393],8125)) {
                pr_warn("error 2\n");
                return -1;
        }
        msleep(1);

        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
                pr_warn("error 3\n");
                return -1;
        }

        /* Wait at least 5 msec */
        msleep(10);
        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
                pr_warn("error 4\n");
                return -1;
        }
        msleep(10);

        pr_info("Done.\n");
        return 0;
};

static int or51211_setmode(struct dvb_frontend* fe, int mode)
{
        struct or51211_state* state = fe->demodulator_priv;
        u8 rec_buf[14];

        state->config->setmode(fe, mode);

        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
                pr_warn("error 1\n");
                return -1;
        }

        /* Wait at least 5 msec */
        msleep(10);
        if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
                pr_warn("error 2\n");
                return -1;
        }

        msleep(10);

        /* Set operation mode in Receiver 1 register;
         * type 1:
         * data 0x50h  Automatic sets receiver channel conditions
         *             Automatic NTSC rejection filter
         *             Enable  MPEG serial data output
         *             MPEG2tr
         *             High tuner phase noise
         *             normal +/-150kHz Carrier acquisition range
         */
        if (i2c_writebytes(state,state->config->demod_address,cmd_buf,3)) {
                pr_warn("error 3\n");
                return -1;
        }

        rec_buf[0] = 0x04;
        rec_buf[1] = 0x00;
        rec_buf[2] = 0x03;
        rec_buf[3] = 0x00;
        msleep(20);
        if (i2c_writebytes(state,state->config->demod_address,rec_buf,3)) {
                pr_warn("error 5\n");
        }
        msleep(3);
        if (i2c_readbytes(state,state->config->demod_address,&rec_buf[10],2)) {
                pr_warn("error 6\n");
                return -1;
        }
        dprintk("rec status %02x %02x\n", rec_buf[10], rec_buf[11]);

        return 0;
}

static int or51211_set_parameters(struct dvb_frontend *fe)
{
        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
        struct or51211_state* state = fe->demodulator_priv;

        /* Change only if we are actually changing the channel */
        if (state->current_frequency != p->frequency) {
                if (fe->ops.tuner_ops.set_params) {
                        fe->ops.tuner_ops.set_params(fe);
                        if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
                }

                /* Set to ATSC mode */
                or51211_setmode(fe,0);

                /* Update current frequency */
                state->current_frequency = p->frequency;
        }
        return 0;
}

static int or51211_read_status(struct dvb_frontend *fe, enum fe_status *status)
{
        struct or51211_state* state = fe->demodulator_priv;
        unsigned char rec_buf[2];
        unsigned char snd_buf[] = {0x04,0x00,0x03,0x00};
        *status = 0;

        /* Receiver Status */
        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
                pr_warn("write error\n");
                return -1;
        }
        msleep(3);
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
                pr_warn("read error\n");
                return -1;
        }
        dprintk("%x %x\n", rec_buf[0], rec_buf[1]);

        if (rec_buf[0] &  0x01) { /* Receiver Lock */
                *status |= FE_HAS_SIGNAL;
                *status |= FE_HAS_CARRIER;
                *status |= FE_HAS_VITERBI;
                *status |= FE_HAS_SYNC;
                *status |= FE_HAS_LOCK;
        }
        return 0;
}

/* Calculate SNR estimation (scaled by 2^24)

   8-VSB SNR equation from Oren datasheets

   For 8-VSB:
     SNR[dB] = 10 * log10(219037.9454 / MSE^2 )

   We re-write the snr equation as:
     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
   Where for 8-VSB, c = log10(219037.9454) * 2^24 */

static u32 calculate_snr(u32 mse, u32 c)
{
        if (mse == 0) /* No signal */
                return 0;

        mse = 2*intlog10(mse);
        if (mse > c) {
                /* Negative SNR, which is possible, but realisticly the
                demod will lose lock before the signal gets this bad.  The
                API only allows for unsigned values, so just return 0 */
                return 0;
        }
        return 10*(c - mse);
}

static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
{
        struct or51211_state* state = fe->demodulator_priv;
        u8 rec_buf[2];
        u8 snd_buf[3];

        /* SNR after Equalizer */
        snd_buf[0] = 0x04;
        snd_buf[1] = 0x00;
        snd_buf[2] = 0x04;

        if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
                pr_warn("error writing snr reg\n");
                return -1;
        }
        if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
                pr_warn("read_status read error\n");
                return -1;
        }

        state->snr = calculate_snr(rec_buf[0], 89599047);
        *snr = (state->snr) >> 16;

        dprintk("noise = 0x%02x, snr = %d.%02d dB\n", rec_buf[0],
                state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);

        return 0;
}

static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
        /* Calculate Strength from SNR up to 35dB */
        /* Even though the SNR can go higher than 35dB, there is some comfort */
        /* factor in having a range of strong signals that can show at 100%   */
        struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
        u16 snr;
        int ret;

        ret = fe->ops.read_snr(fe, &snr);
        if (ret != 0)
                return ret;
        /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
        /* scale the range 0 - 35*2^24 into 0 - 65535 */
        if (state->snr >= 8960 * 0x10000)
                *strength = 0xffff;
        else
                *strength = state->snr / 8960;

        return 0;
}

static int or51211_read_ber(struct dvb_frontend* fe, u32* ber)
{
        *ber = -ENOSYS;
        return 0;
}

static int or51211_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
        *ucblocks = -ENOSYS;
        return 0;
}

static int or51211_sleep(struct dvb_frontend* fe)
{
        return 0;
}

static int or51211_init(struct dvb_frontend* fe)
{
        struct or51211_state* state = fe->demodulator_priv;
        const struct or51211_config* config = state->config;
        const struct firmware* fw;
        unsigned char get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
        unsigned char rec_buf[14];
        int ret,i;

        if (!state->initialized) {
                /* Request the firmware, this will block until it uploads */
                pr_info("Waiting for firmware upload (%s)...\n",
                        OR51211_DEFAULT_FIRMWARE);
                ret = config->request_firmware(fe, &fw,
                                               OR51211_DEFAULT_FIRMWARE);
                pr_info("Got Hotplug firmware\n");
                if (ret) {
                        pr_warn("No firmware uploaded (timeout or file not found?)\n");
                        return ret;
                }

                ret = or51211_load_firmware(fe, fw);
                release_firmware(fw);
                if (ret) {
                        pr_warn("Writing firmware to device failed!\n");
                        return ret;
                }
                pr_info("Firmware upload complete.\n");

                /* Set operation mode in Receiver 1 register;
                 * type 1:
                 * data 0x50h  Automatic sets receiver channel conditions
                 *             Automatic NTSC rejection filter
                 *             Enable  MPEG serial data output
                 *             MPEG2tr
                 *             High tuner phase noise
                 *             normal +/-150kHz Carrier acquisition range
                 */
                if (i2c_writebytes(state,state->config->demod_address,
                                   cmd_buf,3)) {
                        pr_warn("Load DVR Error 5\n");
                        return -1;
                }

                /* Read back ucode version to besure we loaded correctly */
                /* and are really up and running */
                rec_buf[0] = 0x04;
                rec_buf[1] = 0x00;
                rec_buf[2] = 0x03;
                rec_buf[3] = 0x00;
                msleep(30);
                if (i2c_writebytes(state,state->config->demod_address,
                                   rec_buf,3)) {
                        pr_warn("Load DVR Error A\n");
                        return -1;
                }
                msleep(3);
                if (i2c_readbytes(state,state->config->demod_address,
                                  &rec_buf[10],2)) {
                        pr_warn("Load DVR Error B\n");
                        return -1;
                }

                rec_buf[0] = 0x04;
                rec_buf[1] = 0x00;
                rec_buf[2] = 0x01;
                rec_buf[3] = 0x00;
                msleep(20);
                if (i2c_writebytes(state,state->config->demod_address,
                                   rec_buf,3)) {
                        pr_warn("Load DVR Error C\n");
                        return -1;
                }
                msleep(3);
                if (i2c_readbytes(state,state->config->demod_address,
                                  &rec_buf[12],2)) {
                        pr_warn("Load DVR Error D\n");
                        return -1;
                }

                for (i = 0; i < 8; i++)
                        rec_buf[i]=0xed;

                for (i = 0; i < 5; i++) {
                        msleep(30);
                        get_ver_buf[4] = i+1;
                        if (i2c_writebytes(state,state->config->demod_address,
                                           get_ver_buf,5)) {
                                pr_warn("Load DVR Error 6 - %d\n", i);
                                return -1;
                        }
                        msleep(3);

                        if (i2c_readbytes(state,state->config->demod_address,
                                          &rec_buf[i*2],2)) {
                                pr_warn("Load DVR Error 7 - %d\n", i);
                                return -1;
                        }
                        /* If we didn't receive the right index, try again */
                        if ((int)rec_buf[i*2+1]!=i+1){
                          i--;
                        }
                }
                dprintk("read_fwbits %10ph\n", rec_buf);

                pr_info("ver TU%02x%02x%02x VSB mode %02x Status %02x\n",
                        rec_buf[2], rec_buf[4], rec_buf[6], rec_buf[12],
                        rec_buf[10]);

                rec_buf[0] = 0x04;
                rec_buf[1] = 0x00;
                rec_buf[2] = 0x03;
                rec_buf[3] = 0x00;
                msleep(20);
                if (i2c_writebytes(state,state->config->demod_address,
                                   rec_buf,3)) {
                        pr_warn("Load DVR Error 8\n");
                        return -1;
                }
                msleep(20);
                if (i2c_readbytes(state,state->config->demod_address,
                                  &rec_buf[8],2)) {
                        pr_warn("Load DVR Error 9\n");
                        return -1;
                }
                state->initialized = 1;
        }

        return 0;
}

static int or51211_get_tune_settings(struct dvb_frontend* fe,
                                     struct dvb_frontend_tune_settings* fesettings)
{
        fesettings->min_delay_ms = 500;
        fesettings->step_size = 0;
        fesettings->max_drift = 0;
        return 0;
}

static void or51211_release(struct dvb_frontend* fe)
{
        struct or51211_state* state = fe->demodulator_priv;
        state->config->sleep(fe);
        kfree(state);
}

static const struct dvb_frontend_ops or51211_ops;

struct dvb_frontend* or51211_attach(const struct or51211_config* config,
                                    struct i2c_adapter* i2c)
{
        struct or51211_state* state = NULL;

        /* Allocate memory for the internal state */
        state = kzalloc_obj(struct or51211_state);
        if (state == NULL)
                return NULL;

        /* Setup the state */
        state->config = config;
        state->i2c = i2c;
        state->initialized = 0;
        state->current_frequency = 0;

        /* Create dvb_frontend */
        memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
}

static const struct dvb_frontend_ops or51211_ops = {
        .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
        .info = {
                .name                  = "Oren OR51211 VSB Frontend",
                .frequency_min_hz      =  44 * MHz,
                .frequency_max_hz      = 958 * MHz,
                .frequency_stepsize_hz = 166666,
                .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                        FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
                        FE_CAN_8VSB
        },

        .release = or51211_release,

        .init = or51211_init,
        .sleep = or51211_sleep,

        .set_frontend = or51211_set_parameters,
        .get_tune_settings = or51211_get_tune_settings,

        .read_status = or51211_read_status,
        .read_ber = or51211_read_ber,
        .read_signal_strength = or51211_read_signal_strength,
        .read_snr = or51211_read_snr,
        .read_ucblocks = or51211_read_ucblocks,
};

module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");

MODULE_DESCRIPTION("Oren OR51211 VSB [pcHDTV HD-2000] Demodulator Driver");
MODULE_AUTHOR("Kirk Lapray");
MODULE_LICENSE("GPL");

EXPORT_SYMBOL_GPL(or51211_attach);