Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
0002 // Copyright(c) 2015-17 Intel Corporation.
0003 
0004 /*
0005  * MIPI Discovery And Configuration (DisCo) Specification for SoundWire
0006  * specifies properties to be implemented for SoundWire Masters and Slaves.
0007  * The DisCo spec doesn't mandate these properties. However, SDW bus cannot
0008  * work without knowing these values.
0009  *
0010  * The helper functions read the Master and Slave properties. Implementers
0011  * of Master or Slave drivers can use any of the below three mechanisms:
0012  *    a) Use these APIs here as .read_prop() callback for Master and Slave
0013  *    b) Implement own methods and set those as .read_prop(), but invoke
0014  *    APIs in this file for generic read and override the values with
0015  *    platform specific data
0016  *    c) Implement ones own methods which do not use anything provided
0017  *    here
0018  */
0019 
0020 #include <linux/device.h>
0021 #include <linux/property.h>
0022 #include <linux/mod_devicetable.h>
0023 #include <linux/soundwire/sdw.h>
0024 #include "bus.h"
0025 
0026 /**
0027  * sdw_master_read_prop() - Read Master properties
0028  * @bus: SDW bus instance
0029  */
0030 int sdw_master_read_prop(struct sdw_bus *bus)
0031 {
0032     struct sdw_master_prop *prop = &bus->prop;
0033     struct fwnode_handle *link;
0034     char name[32];
0035     int nval, i;
0036 
0037     device_property_read_u32(bus->dev,
0038                  "mipi-sdw-sw-interface-revision",
0039                  &prop->revision);
0040 
0041     /* Find master handle */
0042     snprintf(name, sizeof(name),
0043          "mipi-sdw-link-%d-subproperties", bus->link_id);
0044 
0045     link = device_get_named_child_node(bus->dev, name);
0046     if (!link) {
0047         dev_err(bus->dev, "Master node %s not found\n", name);
0048         return -EIO;
0049     }
0050 
0051     if (fwnode_property_read_bool(link,
0052                       "mipi-sdw-clock-stop-mode0-supported"))
0053         prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
0054 
0055     if (fwnode_property_read_bool(link,
0056                       "mipi-sdw-clock-stop-mode1-supported"))
0057         prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
0058 
0059     fwnode_property_read_u32(link,
0060                  "mipi-sdw-max-clock-frequency",
0061                  &prop->max_clk_freq);
0062 
0063     nval = fwnode_property_count_u32(link, "mipi-sdw-clock-frequencies-supported");
0064     if (nval > 0) {
0065         prop->num_clk_freq = nval;
0066         prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq,
0067                           sizeof(*prop->clk_freq),
0068                           GFP_KERNEL);
0069         if (!prop->clk_freq)
0070             return -ENOMEM;
0071 
0072         fwnode_property_read_u32_array(link,
0073                 "mipi-sdw-clock-frequencies-supported",
0074                 prop->clk_freq, prop->num_clk_freq);
0075     }
0076 
0077     /*
0078      * Check the frequencies supported. If FW doesn't provide max
0079      * freq, then populate here by checking values.
0080      */
0081     if (!prop->max_clk_freq && prop->clk_freq) {
0082         prop->max_clk_freq = prop->clk_freq[0];
0083         for (i = 1; i < prop->num_clk_freq; i++) {
0084             if (prop->clk_freq[i] > prop->max_clk_freq)
0085                 prop->max_clk_freq = prop->clk_freq[i];
0086         }
0087     }
0088 
0089     nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears");
0090     if (nval > 0) {
0091         prop->num_clk_gears = nval;
0092         prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
0093                            sizeof(*prop->clk_gears),
0094                            GFP_KERNEL);
0095         if (!prop->clk_gears)
0096             return -ENOMEM;
0097 
0098         fwnode_property_read_u32_array(link,
0099                            "mipi-sdw-supported-clock-gears",
0100                            prop->clk_gears,
0101                            prop->num_clk_gears);
0102     }
0103 
0104     fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
0105                  &prop->default_frame_rate);
0106 
0107     fwnode_property_read_u32(link, "mipi-sdw-default-frame-row-size",
0108                  &prop->default_row);
0109 
0110     fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
0111                  &prop->default_col);
0112 
0113     prop->dynamic_frame =  fwnode_property_read_bool(link,
0114             "mipi-sdw-dynamic-frame-shape");
0115 
0116     fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
0117                  &prop->err_threshold);
0118 
0119     return 0;
0120 }
0121 EXPORT_SYMBOL(sdw_master_read_prop);
0122 
0123 static int sdw_slave_read_dp0(struct sdw_slave *slave,
0124                   struct fwnode_handle *port,
0125                   struct sdw_dp0_prop *dp0)
0126 {
0127     int nval;
0128 
0129     fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
0130                  &dp0->max_word);
0131 
0132     fwnode_property_read_u32(port, "mipi-sdw-port-min-wordlength",
0133                  &dp0->min_word);
0134 
0135     nval = fwnode_property_count_u32(port, "mipi-sdw-port-wordlength-configs");
0136     if (nval > 0) {
0137 
0138         dp0->num_words = nval;
0139         dp0->words = devm_kcalloc(&slave->dev,
0140                       dp0->num_words, sizeof(*dp0->words),
0141                       GFP_KERNEL);
0142         if (!dp0->words)
0143             return -ENOMEM;
0144 
0145         fwnode_property_read_u32_array(port,
0146                 "mipi-sdw-port-wordlength-configs",
0147                 dp0->words, dp0->num_words);
0148     }
0149 
0150     dp0->BRA_flow_controlled = fwnode_property_read_bool(port,
0151                 "mipi-sdw-bra-flow-controlled");
0152 
0153     dp0->simple_ch_prep_sm = fwnode_property_read_bool(port,
0154                 "mipi-sdw-simplified-channel-prepare-sm");
0155 
0156     dp0->imp_def_interrupts = fwnode_property_read_bool(port,
0157                 "mipi-sdw-imp-def-dp0-interrupts-supported");
0158 
0159     return 0;
0160 }
0161 
0162 static int sdw_slave_read_dpn(struct sdw_slave *slave,
0163                   struct sdw_dpn_prop *dpn, int count, int ports,
0164                   char *type)
0165 {
0166     struct fwnode_handle *node;
0167     u32 bit, i = 0;
0168     int nval;
0169     unsigned long addr;
0170     char name[40];
0171 
0172     addr = ports;
0173     /* valid ports are 1 to 14 so apply mask */
0174     addr &= GENMASK(14, 1);
0175 
0176     for_each_set_bit(bit, &addr, 32) {
0177         snprintf(name, sizeof(name),
0178              "mipi-sdw-dp-%d-%s-subproperties", bit, type);
0179 
0180         dpn[i].num = bit;
0181 
0182         node = device_get_named_child_node(&slave->dev, name);
0183         if (!node) {
0184             dev_err(&slave->dev, "%s dpN not found\n", name);
0185             return -EIO;
0186         }
0187 
0188         fwnode_property_read_u32(node, "mipi-sdw-port-max-wordlength",
0189                      &dpn[i].max_word);
0190         fwnode_property_read_u32(node, "mipi-sdw-port-min-wordlength",
0191                      &dpn[i].min_word);
0192 
0193         nval = fwnode_property_count_u32(node, "mipi-sdw-port-wordlength-configs");
0194         if (nval > 0) {
0195             dpn[i].num_words = nval;
0196             dpn[i].words = devm_kcalloc(&slave->dev,
0197                             dpn[i].num_words,
0198                             sizeof(*dpn[i].words),
0199                             GFP_KERNEL);
0200             if (!dpn[i].words)
0201                 return -ENOMEM;
0202 
0203             fwnode_property_read_u32_array(node,
0204                     "mipi-sdw-port-wordlength-configs",
0205                     dpn[i].words, dpn[i].num_words);
0206         }
0207 
0208         fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
0209                      &dpn[i].type);
0210 
0211         fwnode_property_read_u32(node,
0212                      "mipi-sdw-max-grouping-supported",
0213                      &dpn[i].max_grouping);
0214 
0215         dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node,
0216                 "mipi-sdw-simplified-channelprepare-sm");
0217 
0218         fwnode_property_read_u32(node,
0219                      "mipi-sdw-port-channelprepare-timeout",
0220                      &dpn[i].ch_prep_timeout);
0221 
0222         fwnode_property_read_u32(node,
0223                 "mipi-sdw-imp-def-dpn-interrupts-supported",
0224                 &dpn[i].imp_def_interrupts);
0225 
0226         fwnode_property_read_u32(node, "mipi-sdw-min-channel-number",
0227                      &dpn[i].min_ch);
0228 
0229         fwnode_property_read_u32(node, "mipi-sdw-max-channel-number",
0230                      &dpn[i].max_ch);
0231 
0232         nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list");
0233         if (nval > 0) {
0234             dpn[i].num_channels = nval;
0235             dpn[i].channels = devm_kcalloc(&slave->dev,
0236                                dpn[i].num_channels,
0237                                sizeof(*dpn[i].channels),
0238                          GFP_KERNEL);
0239             if (!dpn[i].channels)
0240                 return -ENOMEM;
0241 
0242             fwnode_property_read_u32_array(node,
0243                     "mipi-sdw-channel-number-list",
0244                     dpn[i].channels, dpn[i].num_channels);
0245         }
0246 
0247         nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
0248         if (nval > 0) {
0249             dpn[i].num_ch_combinations = nval;
0250             dpn[i].ch_combinations = devm_kcalloc(&slave->dev,
0251                     dpn[i].num_ch_combinations,
0252                     sizeof(*dpn[i].ch_combinations),
0253                     GFP_KERNEL);
0254             if (!dpn[i].ch_combinations)
0255                 return -ENOMEM;
0256 
0257             fwnode_property_read_u32_array(node,
0258                     "mipi-sdw-channel-combination-list",
0259                     dpn[i].ch_combinations,
0260                     dpn[i].num_ch_combinations);
0261         }
0262 
0263         fwnode_property_read_u32(node,
0264                 "mipi-sdw-modes-supported", &dpn[i].modes);
0265 
0266         fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
0267                      &dpn[i].max_async_buffer);
0268 
0269         dpn[i].block_pack_mode = fwnode_property_read_bool(node,
0270                 "mipi-sdw-block-packing-mode");
0271 
0272         fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
0273                      &dpn[i].port_encoding);
0274 
0275         /* TODO: Read audio mode */
0276 
0277         i++;
0278     }
0279 
0280     return 0;
0281 }
0282 
0283 /**
0284  * sdw_slave_read_prop() - Read Slave properties
0285  * @slave: SDW Slave
0286  */
0287 int sdw_slave_read_prop(struct sdw_slave *slave)
0288 {
0289     struct sdw_slave_prop *prop = &slave->prop;
0290     struct device *dev = &slave->dev;
0291     struct fwnode_handle *port;
0292     int nval;
0293 
0294     device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
0295                  &prop->mipi_revision);
0296 
0297     prop->wake_capable = device_property_read_bool(dev,
0298                 "mipi-sdw-wake-up-unavailable");
0299     prop->wake_capable = !prop->wake_capable;
0300 
0301     prop->test_mode_capable = device_property_read_bool(dev,
0302                 "mipi-sdw-test-mode-supported");
0303 
0304     prop->clk_stop_mode1 = false;
0305     if (device_property_read_bool(dev,
0306                 "mipi-sdw-clock-stop-mode1-supported"))
0307         prop->clk_stop_mode1 = true;
0308 
0309     prop->simple_clk_stop_capable = device_property_read_bool(dev,
0310             "mipi-sdw-simplified-clockstopprepare-sm-supported");
0311 
0312     device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
0313                  &prop->clk_stop_timeout);
0314 
0315     device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
0316                  &prop->ch_prep_timeout);
0317 
0318     device_property_read_u32(dev,
0319             "mipi-sdw-clockstopprepare-hard-reset-behavior",
0320             &prop->reset_behave);
0321 
0322     prop->high_PHY_capable = device_property_read_bool(dev,
0323             "mipi-sdw-highPHY-capable");
0324 
0325     prop->paging_support = device_property_read_bool(dev,
0326             "mipi-sdw-paging-support");
0327 
0328     prop->bank_delay_support = device_property_read_bool(dev,
0329             "mipi-sdw-bank-delay-support");
0330 
0331     device_property_read_u32(dev,
0332             "mipi-sdw-port15-read-behavior", &prop->p15_behave);
0333 
0334     device_property_read_u32(dev, "mipi-sdw-master-count",
0335                  &prop->master_count);
0336 
0337     device_property_read_u32(dev, "mipi-sdw-source-port-list",
0338                  &prop->source_ports);
0339 
0340     device_property_read_u32(dev, "mipi-sdw-sink-port-list",
0341                  &prop->sink_ports);
0342 
0343     /* Read dp0 properties */
0344     port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
0345     if (!port) {
0346         dev_dbg(dev, "DP0 node not found!!\n");
0347     } else {
0348         prop->dp0_prop = devm_kzalloc(&slave->dev,
0349                           sizeof(*prop->dp0_prop),
0350                           GFP_KERNEL);
0351         if (!prop->dp0_prop)
0352             return -ENOMEM;
0353 
0354         sdw_slave_read_dp0(slave, port, prop->dp0_prop);
0355     }
0356 
0357     /*
0358      * Based on each DPn port, get source and sink dpn properties.
0359      * Also, some ports can operate as both source or sink.
0360      */
0361 
0362     /* Allocate memory for set bits in port lists */
0363     nval = hweight32(prop->source_ports);
0364     prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
0365                       sizeof(*prop->src_dpn_prop),
0366                       GFP_KERNEL);
0367     if (!prop->src_dpn_prop)
0368         return -ENOMEM;
0369 
0370     /* Read dpn properties for source port(s) */
0371     sdw_slave_read_dpn(slave, prop->src_dpn_prop, nval,
0372                prop->source_ports, "source");
0373 
0374     nval = hweight32(prop->sink_ports);
0375     prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
0376                        sizeof(*prop->sink_dpn_prop),
0377                        GFP_KERNEL);
0378     if (!prop->sink_dpn_prop)
0379         return -ENOMEM;
0380 
0381     /* Read dpn properties for sink port(s) */
0382     sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval,
0383                prop->sink_ports, "sink");
0384 
0385     return 0;
0386 }
0387 EXPORT_SYMBOL(sdw_slave_read_prop);