From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/media/i2c/adv748x/adv748x-core.c | 435 ++++++++++++++++++++++++++++++----------------------- 1 files changed, 247 insertions(+), 188 deletions(-) diff --git a/kernel/drivers/media/i2c/adv748x/adv748x-core.c b/kernel/drivers/media/i2c/adv748x/adv748x-core.c index 65c3024..1fe7f97 100644 --- a/kernel/drivers/media/i2c/adv748x/adv748x-core.c +++ b/kernel/drivers/media/i2c/adv748x/adv748x-core.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Analog Devices ADV748X HDMI receiver with AFE * * Copyright (C) 2017 Renesas Electronics Corp. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. * * Authors: * Koji Matsuoka <koji.matsuoka.xm@renesas.com> @@ -27,6 +23,7 @@ #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-dv-timings.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-ioctl.h> #include "adv748x.h" @@ -128,6 +125,16 @@ return regmap_write(state->regmap[page], reg, value); } +static int adv748x_write_check(struct adv748x_state *state, u8 page, u8 reg, + u8 value, int *error) +{ + if (*error) + return *error; + + *error = adv748x_write(state, page, reg, value); + return *error; +} + /* adv748x_write_block(): Write raw data with a maximum of I2C_SMBUS_BLOCK_MAX * size to one or more registers. * @@ -176,14 +183,14 @@ int ret; for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) { - state->i2c_clients[i] = i2c_new_secondary_device( + state->i2c_clients[i] = i2c_new_ancillary_device( state->client, adv748x_default_addresses[i].name, adv748x_default_addresses[i].default_addr); - if (state->i2c_clients[i] == NULL) { + if (IS_ERR(state->i2c_clients[i])) { adv_err(state, "failed to create i2c client %u\n", i); - return -ENOMEM; + return PTR_ERR(state->i2c_clients[i]); } ret = adv748x_configure_regmap(state, i); @@ -211,20 +218,13 @@ { int ret; - while (regs->page != ADV748X_PAGE_EOR) { - if (regs->page == ADV748X_PAGE_WAIT) { - msleep(regs->value); - } else { - ret = adv748x_write(state, regs->page, regs->reg, - regs->value); - if (ret < 0) { - adv_err(state, - "Error regs page: 0x%02x reg: 0x%02x\n", - regs->page, regs->reg); - return ret; - } + for (; regs->page != ADV748X_PAGE_EOR; regs++) { + ret = adv748x_write(state, regs->page, regs->reg, regs->value); + if (ret < 0) { + adv_err(state, "Error regs page: 0x%02x reg: 0x%02x\n", + regs->page, regs->reg); + return ret; } - regs++; } return 0; @@ -234,91 +234,83 @@ * TXA and TXB */ -static const struct adv748x_reg_value adv748x_power_up_txa_4lane[] = { - - {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */ - {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */ - - {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0x1e, 0x40}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ - {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */ - {ADV748X_PAGE_TXA, 0x00, 0x24 },/* Power-up CSI-TX */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXA, 0xc1, 0x2b}, /* ADI Required Write */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXA, 0x31, 0x80}, /* ADI Required Write */ - - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ -}; - -static const struct adv748x_reg_value adv748x_power_down_txa_4lane[] = { - - {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0x1e, 0x00}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */ - {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ - {ADV748X_PAGE_TXA, 0xc1, 0x3b}, /* ADI Required Write */ - - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ -}; - -static const struct adv748x_reg_value adv748x_power_up_txb_1lane[] = { - - {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */ - {ADV748X_PAGE_TXB, 0x00, 0xa1}, /* Set Auto DPHY Timing */ - - {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x1e, 0x40}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ - {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */ - {ADV748X_PAGE_TXB, 0x00, 0x21 },/* Power-up CSI-TX */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXB, 0xc1, 0x2b}, /* ADI Required Write */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXB, 0x31, 0x80}, /* ADI Required Write */ - - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ -}; - -static const struct adv748x_reg_value adv748x_power_down_txb_1lane[] = { - - {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x1e, 0x00}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 4-lane MIPI */ - {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ - {ADV748X_PAGE_TXB, 0xc1, 0x3b}, /* ADI Required Write */ - - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ -}; - -int adv748x_txa_power(struct adv748x_state *state, bool on) +static int adv748x_power_up_tx(struct adv748x_csi2 *tx) { - int val; + struct adv748x_state *state = tx->state; + u8 page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB; + int ret = 0; - val = txa_read(state, ADV748X_CSI_FS_AS_LS); - if (val < 0) - return val; + /* Enable n-lane MIPI */ + adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret); - /* - * This test against BIT(6) is not documented by the datasheet, but was - * specified in the downstream driver. - * Track with a WARN_ONCE to determine if it is ever set by HW. - */ - WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN), - "Enabling with unknown bit set"); + /* Set Auto DPHY Timing */ + adv748x_write_check(state, page, 0x00, 0xa0 | tx->active_lanes, &ret); - if (on) - return adv748x_write_regs(state, adv748x_power_up_txa_4lane); + /* ADI Required Write */ + if (tx->src == &state->hdmi.sd) { + adv748x_write_check(state, page, 0xdb, 0x10, &ret); + adv748x_write_check(state, page, 0xd6, 0x07, &ret); + } else { + adv748x_write_check(state, page, 0xd2, 0x40, &ret); + } - return adv748x_write_regs(state, adv748x_power_down_txa_4lane); + adv748x_write_check(state, page, 0xc4, 0x0a, &ret); + adv748x_write_check(state, page, 0x71, 0x33, &ret); + adv748x_write_check(state, page, 0x72, 0x11, &ret); + + /* i2c_dphy_pwdn - 1'b0 */ + adv748x_write_check(state, page, 0xf0, 0x00, &ret); + + /* ADI Required Writes*/ + adv748x_write_check(state, page, 0x31, 0x82, &ret); + adv748x_write_check(state, page, 0x1e, 0x40, &ret); + + /* i2c_mipi_pll_en - 1'b1 */ + adv748x_write_check(state, page, 0xda, 0x01, &ret); + usleep_range(2000, 2500); + + /* Power-up CSI-TX */ + adv748x_write_check(state, page, 0x00, 0x20 | tx->active_lanes, &ret); + usleep_range(1000, 1500); + + /* ADI Required Writes */ + adv748x_write_check(state, page, 0xc1, 0x2b, &ret); + usleep_range(1000, 1500); + adv748x_write_check(state, page, 0x31, 0x80, &ret); + + return ret; } -int adv748x_txb_power(struct adv748x_state *state, bool on) +static int adv748x_power_down_tx(struct adv748x_csi2 *tx) +{ + struct adv748x_state *state = tx->state; + u8 page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB; + int ret = 0; + + /* ADI Required Writes */ + adv748x_write_check(state, page, 0x31, 0x82, &ret); + adv748x_write_check(state, page, 0x1e, 0x00, &ret); + + /* Enable n-lane MIPI */ + adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret); + + /* i2c_mipi_pll_en - 1'b1 */ + adv748x_write_check(state, page, 0xda, 0x01, &ret); + + /* ADI Required Write */ + adv748x_write_check(state, page, 0xc1, 0x3b, &ret); + + return ret; +} + +int adv748x_tx_power(struct adv748x_csi2 *tx, bool on) { int val; - val = txb_read(state, ADV748X_CSI_FS_AS_LS); + if (!is_tx_enabled(tx)) + return 0; + + val = tx_read(tx, ADV748X_CSI_FS_AS_LS); if (val < 0) return val; @@ -330,15 +322,72 @@ WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN), "Enabling with unknown bit set"); - if (on) - return adv748x_write_regs(state, adv748x_power_up_txb_1lane); - - return adv748x_write_regs(state, adv748x_power_down_txb_1lane); + return on ? adv748x_power_up_tx(tx) : adv748x_power_down_tx(tx); } /* ----------------------------------------------------------------------------- * Media Operations */ +static int adv748x_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *rsd = media_entity_to_v4l2_subdev(remote->entity); + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct adv748x_state *state = v4l2_get_subdevdata(sd); + struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); + bool enable = flags & MEDIA_LNK_FL_ENABLED; + u8 io10_mask = ADV748X_IO_10_CSI1_EN | + ADV748X_IO_10_CSI4_EN | + ADV748X_IO_10_CSI4_IN_SEL_AFE; + u8 io10 = 0; + + /* Refuse to enable multiple links to the same TX at the same time. */ + if (enable && tx->src) + return -EINVAL; + + /* Set or clear the source (HDMI or AFE) and the current TX. */ + if (rsd == &state->afe.sd) + state->afe.tx = enable ? tx : NULL; + else + state->hdmi.tx = enable ? tx : NULL; + + tx->src = enable ? rsd : NULL; + + if (state->afe.tx) { + /* AFE Requires TXA enabled, even when output to TXB */ + io10 |= ADV748X_IO_10_CSI4_EN; + if (is_txa(tx)) { + /* + * Output from the SD-core (480i and 576i) from the TXA + * interface requires reducing the number of enabled + * data lanes in order to guarantee a valid link + * frequency. + */ + tx->active_lanes = min(tx->num_lanes, 2U); + io10 |= ADV748X_IO_10_CSI4_IN_SEL_AFE; + } else { + /* TXB has a single data lane, no need to adjust. */ + io10 |= ADV748X_IO_10_CSI1_EN; + } + } + + if (state->hdmi.tx) { + /* + * Restore the number of active lanes, in case we have gone + * through an AFE->TXA streaming sessions. + */ + tx->active_lanes = tx->num_lanes; + io10 |= ADV748X_IO_10_CSI4_EN; + } + + return io_clrset(state, ADV748X_IO_10, io10_mask, io10); +} + +static const struct media_entity_operations adv748x_tx_media_ops = { + .link_setup = adv748x_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; static const struct media_entity_operations adv748x_media_ops = { .link_validate = v4l2_subdev_link_validate, @@ -348,18 +397,8 @@ * HW setup */ -static const struct adv748x_reg_value adv748x_sw_reset[] = { - - {ADV748X_PAGE_IO, 0xff, 0xff}, /* SW reset */ - {ADV748X_PAGE_WAIT, 0x00, 0x05},/* delay 5 */ - {ADV748X_PAGE_IO, 0x01, 0x76}, /* ADI Required Write */ - {ADV748X_PAGE_IO, 0xf2, 0x01}, /* Enable I2C Read Auto-Increment */ - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ -}; - -/* Supported Formats For Script Below */ -/* - 01-29 HDMI to MIPI TxA CSI 4-Lane - RGB888: */ -static const struct adv748x_reg_value adv748x_init_txa_4lane[] = { +/* Initialize CP Core with RGB888 format. */ +static const struct adv748x_reg_value adv748x_init_hdmi[] = { /* Disable chip powerdown & Enable HDMI Rx block */ {ADV748X_PAGE_IO, 0x00, 0x40}, @@ -399,35 +438,12 @@ {ADV748X_PAGE_IO, 0x0c, 0xe0}, /* Enable LLC_DLL & Double LLC Timing */ {ADV748X_PAGE_IO, 0x0e, 0xdd}, /* LLC/PIX/SPI PINS TRISTATED AUD */ - /* Outputs Enabled */ - {ADV748X_PAGE_IO, 0x10, 0xa0}, /* Enable 4-lane CSI Tx & Pixel Port */ - - {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */ - {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */ - {ADV748X_PAGE_TXA, 0xdb, 0x10}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0xd6, 0x07}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0xc4, 0x0a}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0x71, 0x33}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0x72, 0x11}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0xf0, 0x00}, /* i2c_dphy_pwdn - 1'b0 */ - - {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0x1e, 0x40}, /* ADI Required Write */ - {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ - {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */ - {ADV748X_PAGE_TXA, 0x00, 0x24 },/* Power-up CSI-TX */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXA, 0xc1, 0x2b}, /* ADI Required Write */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXA, 0x31, 0x80}, /* ADI Required Write */ {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ }; -/* 02-01 Analog CVBS to MIPI TX-B CSI 1-Lane - */ -/* Autodetect CVBS Single Ended In Ain 1 - MIPI Out */ -static const struct adv748x_reg_value adv748x_init_txb_1lane[] = { - +/* Initialize AFE core with YUV8 format. */ +static const struct adv748x_reg_value adv748x_init_afe[] = { {ADV748X_PAGE_IO, 0x00, 0x30}, /* Disable chip powerdown Rx */ {ADV748X_PAGE_IO, 0xf2, 0x01}, /* Enable I2C Read Auto-Increment */ @@ -454,36 +470,36 @@ {ADV748X_PAGE_SDP, 0x31, 0x12}, /* ADI Required Write */ {ADV748X_PAGE_SDP, 0xe6, 0x4f}, /* V bit end pos manually in NTSC */ - /* Enable 1-Lane MIPI Tx, */ - /* enable pixel output and route SD through Pixel port */ - {ADV748X_PAGE_IO, 0x10, 0x70}, - - {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */ - {ADV748X_PAGE_TXB, 0x00, 0xa1}, /* Set Auto DPHY Timing */ - {ADV748X_PAGE_TXB, 0xd2, 0x40}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0xc4, 0x0a}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x71, 0x33}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x72, 0x11}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0xf0, 0x00}, /* i2c_dphy_pwdn - 1'b0 */ - {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x1e, 0x40}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ - - {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */ - {ADV748X_PAGE_TXB, 0x00, 0x21 },/* Power-up CSI-TX */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXB, 0xc1, 0x2b}, /* ADI Required Write */ - {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */ - {ADV748X_PAGE_TXB, 0x31, 0x80}, /* ADI Required Write */ - {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ }; + +static int adv748x_sw_reset(struct adv748x_state *state) +{ + int ret; + + ret = io_write(state, ADV748X_IO_REG_FF, ADV748X_IO_REG_FF_MAIN_RESET); + if (ret) + return ret; + + usleep_range(5000, 6000); + + /* Disable CEC Wakeup from power-down mode */ + ret = io_clrset(state, ADV748X_IO_REG_01, ADV748X_IO_REG_01_PWRDN_MASK, + ADV748X_IO_REG_01_PWRDNB); + if (ret) + return ret; + + /* Enable I2C Read Auto-Increment for consecutive reads */ + return io_write(state, ADV748X_IO_REG_F2, + ADV748X_IO_REG_F2_READ_AUTO_INC); +} static int adv748x_reset(struct adv748x_state *state) { int ret; + u8 regval = 0; - ret = adv748x_write_regs(state, adv748x_sw_reset); + ret = adv748x_sw_reset(state); if (ret < 0) return ret; @@ -491,27 +507,30 @@ if (ret < 0) return ret; - /* Init and power down TXA */ - ret = adv748x_write_regs(state, adv748x_init_txa_4lane); + /* Initialize CP and AFE cores. */ + ret = adv748x_write_regs(state, adv748x_init_hdmi); if (ret) return ret; - adv748x_txa_power(state, 0); - - /* Init and power down TXB */ - ret = adv748x_write_regs(state, adv748x_init_txb_1lane); + ret = adv748x_write_regs(state, adv748x_init_afe); if (ret) return ret; - adv748x_txb_power(state, 0); + /* Reset TXA and TXB */ + adv748x_tx_power(&state->txa, 1); + adv748x_tx_power(&state->txa, 0); + adv748x_tx_power(&state->txb, 1); + adv748x_tx_power(&state->txb, 0); /* Disable chip powerdown & Enable HDMI Rx block */ io_write(state, ADV748X_IO_PD, ADV748X_IO_PD_RX_EN); - /* Enable 4-lane CSI Tx & Pixel Port */ - io_write(state, ADV748X_IO_10, ADV748X_IO_10_CSI4_EN | - ADV748X_IO_10_CSI1_EN | - ADV748X_IO_10_PIX_OUT_EN); + /* Conditionally enable TXa and TXb. */ + if (is_tx_enabled(&state->txa)) + regval |= ADV748X_IO_10_CSI4_EN; + if (is_tx_enabled(&state->txb)) + regval |= ADV748X_IO_10_CSI1_EN; + io_write(state, ADV748X_IO_10, regval); /* Use vid_std and v_freq as freerun resolution for CP */ cp_clrset(state, ADV748X_CP_CLMP_POS, ADV748X_CP_CLMP_POS_DIS_AUTO, @@ -562,7 +581,53 @@ state->client->addr, ident); sd->entity.function = function; - sd->entity.ops = &adv748x_media_ops; + sd->entity.ops = is_tx(adv748x_sd_to_csi2(sd)) ? + &adv748x_tx_media_ops : &adv748x_media_ops; +} + +static int adv748x_parse_csi2_lanes(struct adv748x_state *state, + unsigned int port, + struct device_node *ep) +{ + struct v4l2_fwnode_endpoint vep; + unsigned int num_lanes; + int ret; + + if (port != ADV748X_PORT_TXA && port != ADV748X_PORT_TXB) + return 0; + + vep.bus_type = V4L2_MBUS_CSI2_DPHY; + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &vep); + if (ret) + return ret; + + num_lanes = vep.bus.mipi_csi2.num_data_lanes; + + if (vep.base.port == ADV748X_PORT_TXA) { + if (num_lanes != 1 && num_lanes != 2 && num_lanes != 4) { + adv_err(state, "TXA: Invalid number (%u) of lanes\n", + num_lanes); + return -EINVAL; + } + + state->txa.num_lanes = num_lanes; + state->txa.active_lanes = num_lanes; + adv_dbg(state, "TXA: using %u lanes\n", state->txa.num_lanes); + } + + if (vep.base.port == ADV748X_PORT_TXB) { + if (num_lanes != 1) { + adv_err(state, "TXB: Invalid number (%u) of lanes\n", + num_lanes); + return -EINVAL; + } + + state->txb.num_lanes = num_lanes; + state->txb.active_lanes = num_lanes; + adv_dbg(state, "TXB: using %u lanes\n", state->txb.num_lanes); + } + + return 0; } static int adv748x_parse_dt(struct adv748x_state *state) @@ -571,6 +636,7 @@ struct of_endpoint ep; bool out_found = false; bool in_found = false; + int ret; for_each_endpoint_of_node(state->dev->of_node, ep_np) { of_graph_parse_endpoint(ep_np, &ep); @@ -601,6 +667,11 @@ in_found = true; else out_found = true; + + /* Store number of CSI-2 lanes used for TXA and TXB. */ + ret = adv748x_parse_csi2_lanes(state, ep.port, ep_np); + if (ret) + return ret; } return in_found && out_found ? 0 : -ENODEV; @@ -614,8 +685,7 @@ of_node_put(state->endpoints[i]); } -static int adv748x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adv748x_probe(struct i2c_client *client) { struct adv748x_state *state; int ret; @@ -624,7 +694,7 @@ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - state = kzalloc(sizeof(struct adv748x_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; @@ -722,7 +792,6 @@ adv748x_dt_cleanup(state); err_free_mutex: mutex_destroy(&state->mutex); - kfree(state); return ret; } @@ -741,17 +810,8 @@ adv748x_dt_cleanup(state); mutex_destroy(&state->mutex); - kfree(state); - return 0; } - -static const struct i2c_device_id adv748x_id[] = { - { "adv7481", 0 }, - { "adv7482", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, adv748x_id); static const struct of_device_id adv748x_of_table[] = { { .compatible = "adi,adv7481", }, @@ -765,13 +825,12 @@ .name = "adv748x", .of_match_table = adv748x_of_table, }, - .probe = adv748x_probe, + .probe_new = adv748x_probe, .remove = adv748x_remove, - .id_table = adv748x_id, }; module_i2c_driver(adv748x_driver); MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>"); MODULE_DESCRIPTION("ADV748X video decoder"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); -- Gitblit v1.6.2