// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices AD9389B/AD9889B video encoder driver
*
* Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
/*
* References (c = chapter, p = page):
* REF_01 - Analog Devices, Programming Guide, AD9889B/AD9389B,
* HDMI Transitter, Rev. A, October 2010
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#include <linux/v4l2-dv-timings.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
#include <media/v4l2-dv-timings.h>
#include <media/v4l2-ctrls.h>
#include <media/i2c/ad9389b.h>
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_DESCRIPTION("Analog Devices AD9389B/AD9889B video encoder driver");
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
MODULE_LICENSE("GPL");
#define MASK_AD9389B_EDID_RDY_INT 0x04
#define MASK_AD9389B_MSEN_INT 0x40
#define MASK_AD9389B_HPD_INT 0x80
#define MASK_AD9389B_HPD_DETECT 0x40
#define MASK_AD9389B_MSEN_DETECT 0x20
#define MASK_AD9389B_EDID_RDY 0x10
#define EDID_MAX_RETRIES (8)
#define EDID_DELAY 250
#define EDID_MAX_SEGM 8
/*
**********************************************************************
*
* Arrays with configuration parameters for the AD9389B
*
**********************************************************************
*/
struct ad9389b_state_edid {
/* total number of blocks */
u32 blocks;
/* Number of segments read */
u32 segments;
u8 data[EDID_MAX_SEGM * 256];
/* Number of EDID read retries left */
unsigned read_retries;
};
struct ad9389b_state {
struct ad9389b_platform_data pdata;
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler hdl;
int chip_revision;
/* Is the ad9389b powered on? */
bool power_on;
/* Did we receive hotplug and rx-sense signals? */
bool have_monitor;
/* timings from s_dv_timings */
struct v4l2_dv_timings dv_timings;
/* controls */
struct v4l2_ctrl *hdmi_mode_ctrl;
struct v4l2_ctrl *hotplug_ctrl;
struct v4l2_ctrl *rx_sense_ctrl;
struct v4l2_ctrl *have_edid0_ctrl;
struct v4l2_ctrl *rgb_quantization_range_ctrl;
struct i2c_client *edid_i2c_client;
struct ad9389b_state_edid edid;
/* Running counter of the number of detected EDIDs (for debugging) */
unsigned edid_detect_counter;
struct delayed_work edid_handler; /* work entry */
};
static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd);
static bool ad9389b_check_edid_status(struct v4l2_subdev *sd);
static void ad9389b_setup(struct v4l2_subdev *sd);
static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq);
static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
static inline struct ad9389b_state *get_ad9389b_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct ad9389b_state, sd);
}
static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
{
return &container_of(ctrl->handler, struct ad9389b_state, hdl)->sd;
}
/* ------------------------ I2C ----------------------------------------------- */
static int ad9389b_rd(struct v4l2_subdev *sd, u8 reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
return i2c_smbus_read_byte_data(client, reg);
}
static int ad9389b_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret;
int i;
for (i = 0; i < 3; i++) {
ret = i2c_smbus_write_byte_data(client, reg, val);
if (ret == 0)
return 0;
}
v4l2_err(sd, "%s: failed reg 0x%x, val 0x%x\n", __func__, reg, val);
return ret;
}
/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
and then the value-mask (to be OR-ed). */
static inline void ad9389b_wr_and_or