linux/drivers/media/pci/intel/ipu3/cio2-bridge.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Author: Dan Scally <djrscally@gmail.com> */
   3
   4#include <linux/acpi.h>
   5#include <linux/device.h>
   6#include <linux/pci.h>
   7#include <linux/property.h>
   8#include <media/v4l2-fwnode.h>
   9
  10#include "cio2-bridge.h"
  11
  12/*
  13 * Extend this array with ACPI Hardware IDs of devices known to be working
  14 * plus the number of link-frequencies expected by their drivers, along with
  15 * the frequency values in hertz. This is somewhat opportunistic way of adding
  16 * support for this for now in the hopes of a better source for the information
  17 * (possibly some encoded value in the SSDB buffer that we're unaware of)
  18 * becoming apparent in the future.
  19 *
  20 * Do not add an entry for a sensor that is not actually supported.
  21 */
  22static const struct cio2_sensor_config cio2_supported_sensors[] = {
  23        /* Omnivision OV5693 */
  24        CIO2_SENSOR_CONFIG("INT33BE", 0),
  25        /* Omnivision OV2680 */
  26        CIO2_SENSOR_CONFIG("OVTI2680", 0),
  27};
  28
  29static const struct cio2_property_names prop_names = {
  30        .clock_frequency = "clock-frequency",
  31        .rotation = "rotation",
  32        .bus_type = "bus-type",
  33        .data_lanes = "data-lanes",
  34        .remote_endpoint = "remote-endpoint",
  35        .link_frequencies = "link-frequencies",
  36};
  37
  38static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
  39                                        void *data, u32 size)
  40{
  41        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  42        union acpi_object *obj;
  43        acpi_status status;
  44        int ret = 0;
  45
  46        status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
  47        if (ACPI_FAILURE(status))
  48                return -ENODEV;
  49
  50        obj = buffer.pointer;
  51        if (!obj) {
  52                dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
  53                return -ENODEV;
  54        }
  55
  56        if (obj->type != ACPI_TYPE_BUFFER) {
  57                dev_err(&adev->dev, "Not an ACPI buffer\n");
  58                ret = -ENODEV;
  59                goto out_free_buff;
  60        }
  61
  62        if (obj->buffer.length > size) {
  63                dev_err(&adev->dev, "Given buffer is too small\n");
  64                ret = -EINVAL;
  65                goto out_free_buff;
  66        }
  67
  68        memcpy(data, obj->buffer.pointer, obj->buffer.length);
  69
  70out_free_buff:
  71        kfree(buffer.pointer);
  72        return ret;
  73}
  74
  75static void cio2_bridge_create_fwnode_properties(
  76        struct cio2_sensor *sensor,
  77        struct cio2_bridge *bridge,
  78        const struct cio2_sensor_config *cfg)
  79{
  80        sensor->prop_names = prop_names;
  81
  82        sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]);
  83        sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]);
  84
  85        sensor->dev_properties[0] = PROPERTY_ENTRY_U32(
  86                                        sensor->prop_names.clock_frequency,
  87                                        sensor->ssdb.mclkspeed);
  88        sensor->dev_properties[1] = PROPERTY_ENTRY_U8(
  89                                        sensor->prop_names.rotation,
  90                                        sensor->ssdb.degree);
  91
  92        sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
  93                                        sensor->prop_names.bus_type,
  94                                        V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
  95        sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(
  96                                        sensor->prop_names.data_lanes,
  97                                        bridge->data_lanes,
  98                                        sensor->ssdb.lanes);
  99        sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(
 100                                        sensor->prop_names.remote_endpoint,
 101                                        sensor->local_ref);
 102
 103        if (cfg->nr_link_freqs > 0)
 104                sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN(
 105                        sensor->prop_names.link_frequencies,
 106                        cfg->link_freqs,
 107                        cfg->nr_link_freqs);
 108
 109        sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
 110                                        sensor->prop_names.data_lanes,
 111                                        bridge->data_lanes,
 112                                        sensor->ssdb.lanes);
 113        sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(
 114                                        sensor->prop_names.remote_endpoint,
 115                                        sensor->remote_ref);
 116}
 117
 118static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
 119{
 120        snprintf(sensor->node_names.remote_port,
 121                 sizeof(sensor->node_names.remote_port),
 122                 SWNODE_GRAPH_PORT_NAME_FMT, sensor->ssdb.link);
 123        snprintf(sensor->node_names.port,
 124                 sizeof(sensor->node_names.port),
 125                 SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */
 126        snprintf(sensor->node_names.endpoint,
 127                 sizeof(sensor->node_names.endpoint),
 128                 SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */
 129}
 130
 131static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
 132                                                  struct cio2_sensor *sensor)
 133{
 134        struct software_node *nodes = sensor->swnodes;
 135
 136        cio2_bridge_init_swnode_names(sensor);
 137
 138        nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
 139                                               sensor->dev_properties);
 140        nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
 141                                              &nodes[SWNODE_SENSOR_HID]);
 142        nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(
 143                                                sensor->node_names.endpoint,
 144                                                &nodes[SWNODE_SENSOR_PORT],
 145                                                sensor->ep_properties);
 146        nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
 147                                            &bridge->cio2_hid_node);
 148        nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(
 149                                                sensor->node_names.endpoint,
 150                                                &nodes[SWNODE_CIO2_PORT],
 151                                                sensor->cio2_properties);
 152}
 153
 154static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
 155{
 156        struct cio2_sensor *sensor;
 157        unsigned int i;
 158
 159        for (i = 0; i < bridge->n_sensors; i++) {
 160                sensor = &bridge->sensors[i];
 161                software_node_unregister_nodes(sensor->swnodes);
 162                acpi_dev_put(sensor->adev);
 163        }
 164}
 165
 166static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
 167                                      struct cio2_bridge *bridge,
 168                                      struct pci_dev *cio2)
 169{
 170        struct fwnode_handle *fwnode;
 171        struct cio2_sensor *sensor;
 172        struct acpi_device *adev;
 173        int ret;
 174
 175        for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
 176                if (!adev->status.enabled)
 177                        continue;
 178
 179                if (bridge->n_sensors >= CIO2_NUM_PORTS) {
 180                        acpi_dev_put(adev);
 181                        dev_err(&cio2->dev, "Exceeded available CIO2 ports\n");
 182                        return -EINVAL;
 183                }
 184
 185                sensor = &bridge->sensors[bridge->n_sensors];
 186                strscpy(sensor->name, cfg->hid, sizeof(sensor->name));
 187
 188                ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
 189                                                   &sensor->ssdb,
 190                                                   sizeof(sensor->ssdb));
 191                if (ret)
 192                        goto err_put_adev;
 193
 194                if (sensor->ssdb.lanes > CIO2_MAX_LANES) {
 195                        dev_err(&adev->dev,
 196                                "Number of lanes in SSDB is invalid\n");
 197                        ret = -EINVAL;
 198                        goto err_put_adev;
 199                }
 200
 201                cio2_bridge_create_fwnode_properties(sensor, bridge, cfg);
 202                cio2_bridge_create_connection_swnodes(bridge, sensor);
 203
 204                ret = software_node_register_nodes(sensor->swnodes);
 205                if (ret)
 206                        goto err_put_adev;
 207
 208                fwnode = software_node_fwnode(&sensor->swnodes[
 209                                                      SWNODE_SENSOR_HID]);
 210                if (!fwnode) {
 211                        ret = -ENODEV;
 212                        goto err_free_swnodes;
 213                }
 214
 215                sensor->adev = acpi_dev_get(adev);
 216                adev->fwnode.secondary = fwnode;
 217
 218                dev_info(&cio2->dev, "Found supported sensor %s\n",
 219                         acpi_dev_name(adev));
 220
 221                bridge->n_sensors++;
 222        }
 223
 224        return 0;
 225
 226err_free_swnodes:
 227        software_node_unregister_nodes(sensor->swnodes);
 228err_put_adev:
 229        acpi_dev_put(adev);
 230        return ret;
 231}
 232
 233static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge,
 234                                       struct pci_dev *cio2)
 235{
 236        unsigned int i;
 237        int ret;
 238
 239        for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) {
 240                const struct cio2_sensor_config *cfg =
 241                        &cio2_supported_sensors[i];
 242
 243                ret = cio2_bridge_connect_sensor(cfg, bridge, cio2);
 244                if (ret)
 245                        goto err_unregister_sensors;
 246        }
 247
 248        return 0;
 249
 250err_unregister_sensors:
 251        cio2_bridge_unregister_sensors(bridge);
 252        return ret;
 253}
 254
 255int cio2_bridge_init(struct pci_dev *cio2)
 256{
 257        struct device *dev = &cio2->dev;
 258        struct fwnode_handle *fwnode;
 259        struct cio2_bridge *bridge;
 260        unsigned int i;
 261        int ret;
 262
 263        bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
 264        if (!bridge)
 265                return -ENOMEM;
 266
 267        strscpy(bridge->cio2_node_name, CIO2_HID,
 268                sizeof(bridge->cio2_node_name));
 269        bridge->cio2_hid_node.name = bridge->cio2_node_name;
 270
 271        ret = software_node_register(&bridge->cio2_hid_node);
 272        if (ret < 0) {
 273                dev_err(dev, "Failed to register the CIO2 HID node\n");
 274                goto err_free_bridge;
 275        }
 276
 277        /*
 278         * Map the lane arrangement, which is fixed for the IPU3 (meaning we
 279         * only need one, rather than one per sensor). We include it as a
 280         * member of the struct cio2_bridge rather than a global variable so
 281         * that it survives if the module is unloaded along with the rest of
 282         * the struct.
 283         */
 284        for (i = 0; i < CIO2_MAX_LANES; i++)
 285                bridge->data_lanes[i] = i + 1;
 286
 287        ret = cio2_bridge_connect_sensors(bridge, cio2);
 288        if (ret || bridge->n_sensors == 0)
 289                goto err_unregister_cio2;
 290
 291        dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
 292
 293        fwnode = software_node_fwnode(&bridge->cio2_hid_node);
 294        if (!fwnode) {
 295                dev_err(dev, "Error getting fwnode from cio2 software_node\n");
 296                ret = -ENODEV;
 297                goto err_unregister_sensors;
 298        }
 299
 300        set_secondary_fwnode(dev, fwnode);
 301
 302        return 0;
 303
 304err_unregister_sensors:
 305        cio2_bridge_unregister_sensors(bridge);
 306err_unregister_cio2:
 307        software_node_unregister(&bridge->cio2_hid_node);
 308err_free_bridge:
 309        kfree(bridge);
 310
 311        return ret;
 312}
 313