root/drivers/soundwire/mipi_disco.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sdw_master_read_prop
  2. sdw_slave_read_dp0
  3. sdw_slave_read_dpn
  4. sdw_slave_read_prop

   1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
   2 // Copyright(c) 2015-17 Intel Corporation.
   3 
   4 /*
   5  * MIPI Discovery And Configuration (DisCo) Specification for SoundWire
   6  * specifies properties to be implemented for SoundWire Masters and Slaves.
   7  * The DisCo spec doesn't mandate these properties. However, SDW bus cannot
   8  * work without knowing these values.
   9  *
  10  * The helper functions read the Master and Slave properties. Implementers
  11  * of Master or Slave drivers can use any of the below three mechanisms:
  12  *    a) Use these APIs here as .read_prop() callback for Master and Slave
  13  *    b) Implement own methods and set those as .read_prop(), but invoke
  14  *    APIs in this file for generic read and override the values with
  15  *    platform specific data
  16  *    c) Implement ones own methods which do not use anything provided
  17  *    here
  18  */
  19 
  20 #include <linux/device.h>
  21 #include <linux/property.h>
  22 #include <linux/mod_devicetable.h>
  23 #include <linux/soundwire/sdw.h>
  24 #include "bus.h"
  25 
  26 /**
  27  * sdw_master_read_prop() - Read Master properties
  28  * @bus: SDW bus instance
  29  */
  30 int sdw_master_read_prop(struct sdw_bus *bus)
  31 {
  32         struct sdw_master_prop *prop = &bus->prop;
  33         struct fwnode_handle *link;
  34         char name[32];
  35         int nval, i;
  36 
  37         device_property_read_u32(bus->dev,
  38                                  "mipi-sdw-sw-interface-revision",
  39                                  &prop->revision);
  40 
  41         /* Find master handle */
  42         snprintf(name, sizeof(name),
  43                  "mipi-sdw-link-%d-subproperties", bus->link_id);
  44 
  45         link = device_get_named_child_node(bus->dev, name);
  46         if (!link) {
  47                 dev_err(bus->dev, "Master node %s not found\n", name);
  48                 return -EIO;
  49         }
  50 
  51         if (fwnode_property_read_bool(link,
  52                                       "mipi-sdw-clock-stop-mode0-supported"))
  53                 prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
  54 
  55         if (fwnode_property_read_bool(link,
  56                                       "mipi-sdw-clock-stop-mode1-supported"))
  57                 prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
  58 
  59         fwnode_property_read_u32(link,
  60                                  "mipi-sdw-max-clock-frequency",
  61                                  &prop->max_clk_freq);
  62 
  63         nval = fwnode_property_count_u32(link, "mipi-sdw-clock-frequencies-supported");
  64         if (nval > 0) {
  65                 prop->num_clk_freq = nval;
  66                 prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq,
  67                                               sizeof(*prop->clk_freq),
  68                                               GFP_KERNEL);
  69                 if (!prop->clk_freq)
  70                         return -ENOMEM;
  71 
  72                 fwnode_property_read_u32_array(link,
  73                                 "mipi-sdw-clock-frequencies-supported",
  74                                 prop->clk_freq, prop->num_clk_freq);
  75         }
  76 
  77         /*
  78          * Check the frequencies supported. If FW doesn't provide max
  79          * freq, then populate here by checking values.
  80          */
  81         if (!prop->max_clk_freq && prop->clk_freq) {
  82                 prop->max_clk_freq = prop->clk_freq[0];
  83                 for (i = 1; i < prop->num_clk_freq; i++) {
  84                         if (prop->clk_freq[i] > prop->max_clk_freq)
  85                                 prop->max_clk_freq = prop->clk_freq[i];
  86                 }
  87         }
  88 
  89         nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears");
  90         if (nval > 0) {
  91                 prop->num_clk_gears = nval;
  92                 prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
  93                                                sizeof(*prop->clk_gears),
  94                                                GFP_KERNEL);
  95                 if (!prop->clk_gears)
  96                         return -ENOMEM;
  97 
  98                 fwnode_property_read_u32_array(link,
  99                                                "mipi-sdw-supported-clock-gears",
 100                                                prop->clk_gears,
 101                                                prop->num_clk_gears);
 102         }
 103 
 104         fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
 105                                  &prop->default_frame_rate);
 106 
 107         fwnode_property_read_u32(link, "mipi-sdw-default-frame-row-size",
 108                                  &prop->default_row);
 109 
 110         fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
 111                                  &prop->default_col);
 112 
 113         prop->dynamic_frame =  fwnode_property_read_bool(link,
 114                         "mipi-sdw-dynamic-frame-shape");
 115 
 116         fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
 117                                  &prop->err_threshold);
 118 
 119         return 0;
 120 }
 121 EXPORT_SYMBOL(sdw_master_read_prop);
 122 
 123 static int sdw_slave_read_dp0(struct sdw_slave *slave,
 124                               struct fwnode_handle *port,
 125                               struct sdw_dp0_prop *dp0)
 126 {
 127         int nval;
 128 
 129         fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
 130                                  &dp0->max_word);
 131 
 132         fwnode_property_read_u32(port, "mipi-sdw-port-min-wordlength",
 133                                  &dp0->min_word);
 134 
 135         nval = fwnode_property_count_u32(port, "mipi-sdw-port-wordlength-configs");
 136         if (nval > 0) {
 137 
 138                 dp0->num_words = nval;
 139                 dp0->words = devm_kcalloc(&slave->dev,
 140                                           dp0->num_words, sizeof(*dp0->words),
 141                                           GFP_KERNEL);
 142                 if (!dp0->words)
 143                         return -ENOMEM;
 144 
 145                 fwnode_property_read_u32_array(port,
 146                                 "mipi-sdw-port-wordlength-configs",
 147                                 dp0->words, dp0->num_words);
 148         }
 149 
 150         dp0->BRA_flow_controlled = fwnode_property_read_bool(port,
 151                                 "mipi-sdw-bra-flow-controlled");
 152 
 153         dp0->simple_ch_prep_sm = fwnode_property_read_bool(port,
 154                                 "mipi-sdw-simplified-channel-prepare-sm");
 155 
 156         dp0->imp_def_interrupts = fwnode_property_read_bool(port,
 157                                 "mipi-sdw-imp-def-dp0-interrupts-supported");
 158 
 159         return 0;
 160 }
 161 
 162 static int sdw_slave_read_dpn(struct sdw_slave *slave,
 163                               struct sdw_dpn_prop *dpn, int count, int ports,
 164                               char *type)
 165 {
 166         struct fwnode_handle *node;
 167         u32 bit, i = 0;
 168         int nval;
 169         unsigned long addr;
 170         char name[40];
 171 
 172         addr = ports;
 173         /* valid ports are 1 to 14 so apply mask */
 174         addr &= GENMASK(14, 1);
 175 
 176         for_each_set_bit(bit, &addr, 32) {
 177                 snprintf(name, sizeof(name),
 178                          "mipi-sdw-dp-%d-%s-subproperties", bit, type);
 179 
 180                 dpn[i].num = bit;
 181 
 182                 node = device_get_named_child_node(&slave->dev, name);
 183                 if (!node) {
 184                         dev_err(&slave->dev, "%s dpN not found\n", name);
 185                         return -EIO;
 186                 }
 187 
 188                 fwnode_property_read_u32(node, "mipi-sdw-port-max-wordlength",
 189                                          &dpn[i].max_word);
 190                 fwnode_property_read_u32(node, "mipi-sdw-port-min-wordlength",
 191                                          &dpn[i].min_word);
 192 
 193                 nval = fwnode_property_count_u32(node, "mipi-sdw-port-wordlength-configs");
 194                 if (nval > 0) {
 195                         dpn[i].num_words = nval;
 196                         dpn[i].words = devm_kcalloc(&slave->dev,
 197                                                     dpn[i].num_words,
 198                                                     sizeof(*dpn[i].words),
 199                                                     GFP_KERNEL);
 200                         if (!dpn[i].words)
 201                                 return -ENOMEM;
 202 
 203                         fwnode_property_read_u32_array(node,
 204                                         "mipi-sdw-port-wordlength-configs",
 205                                         dpn[i].words, dpn[i].num_words);
 206                 }
 207 
 208                 fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
 209                                          &dpn[i].type);
 210 
 211                 fwnode_property_read_u32(node,
 212                                          "mipi-sdw-max-grouping-supported",
 213                                          &dpn[i].max_grouping);
 214 
 215                 dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node,
 216                                 "mipi-sdw-simplified-channelprepare-sm");
 217 
 218                 fwnode_property_read_u32(node,
 219                                          "mipi-sdw-port-channelprepare-timeout",
 220                                          &dpn[i].ch_prep_timeout);
 221 
 222                 fwnode_property_read_u32(node,
 223                                 "mipi-sdw-imp-def-dpn-interrupts-supported",
 224                                 &dpn[i].imp_def_interrupts);
 225 
 226                 fwnode_property_read_u32(node, "mipi-sdw-min-channel-number",
 227                                          &dpn[i].min_ch);
 228 
 229                 fwnode_property_read_u32(node, "mipi-sdw-max-channel-number",
 230                                          &dpn[i].max_ch);
 231 
 232                 nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list");
 233                 if (nval > 0) {
 234                         dpn[i].num_ch = nval;
 235                         dpn[i].ch = devm_kcalloc(&slave->dev, dpn[i].num_ch,
 236                                                  sizeof(*dpn[i].ch),
 237                                                  GFP_KERNEL);
 238                         if (!dpn[i].ch)
 239                                 return -ENOMEM;
 240 
 241                         fwnode_property_read_u32_array(node,
 242                                         "mipi-sdw-channel-number-list",
 243                                         dpn[i].ch, dpn[i].num_ch);
 244                 }
 245 
 246                 nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
 247                 if (nval > 0) {
 248                         dpn[i].num_ch_combinations = nval;
 249                         dpn[i].ch_combinations = devm_kcalloc(&slave->dev,
 250                                         dpn[i].num_ch_combinations,
 251                                         sizeof(*dpn[i].ch_combinations),
 252                                         GFP_KERNEL);
 253                         if (!dpn[i].ch_combinations)
 254                                 return -ENOMEM;
 255 
 256                         fwnode_property_read_u32_array(node,
 257                                         "mipi-sdw-channel-combination-list",
 258                                         dpn[i].ch_combinations,
 259                                         dpn[i].num_ch_combinations);
 260                 }
 261 
 262                 fwnode_property_read_u32(node,
 263                                 "mipi-sdw-modes-supported", &dpn[i].modes);
 264 
 265                 fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
 266                                          &dpn[i].max_async_buffer);
 267 
 268                 dpn[i].block_pack_mode = fwnode_property_read_bool(node,
 269                                 "mipi-sdw-block-packing-mode");
 270 
 271                 fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
 272                                          &dpn[i].port_encoding);
 273 
 274                 /* TODO: Read audio mode */
 275 
 276                 i++;
 277         }
 278 
 279         return 0;
 280 }
 281 
 282 /**
 283  * sdw_slave_read_prop() - Read Slave properties
 284  * @slave: SDW Slave
 285  */
 286 int sdw_slave_read_prop(struct sdw_slave *slave)
 287 {
 288         struct sdw_slave_prop *prop = &slave->prop;
 289         struct device *dev = &slave->dev;
 290         struct fwnode_handle *port;
 291         int num_of_ports, nval, i, dp0 = 0;
 292 
 293         device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
 294                                  &prop->mipi_revision);
 295 
 296         prop->wake_capable = device_property_read_bool(dev,
 297                                 "mipi-sdw-wake-up-unavailable");
 298         prop->wake_capable = !prop->wake_capable;
 299 
 300         prop->test_mode_capable = device_property_read_bool(dev,
 301                                 "mipi-sdw-test-mode-supported");
 302 
 303         prop->clk_stop_mode1 = false;
 304         if (device_property_read_bool(dev,
 305                                 "mipi-sdw-clock-stop-mode1-supported"))
 306                 prop->clk_stop_mode1 = true;
 307 
 308         prop->simple_clk_stop_capable = device_property_read_bool(dev,
 309                         "mipi-sdw-simplified-clockstopprepare-sm-supported");
 310 
 311         device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
 312                                  &prop->clk_stop_timeout);
 313 
 314         device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
 315                                  &prop->ch_prep_timeout);
 316 
 317         device_property_read_u32(dev,
 318                         "mipi-sdw-clockstopprepare-hard-reset-behavior",
 319                         &prop->reset_behave);
 320 
 321         prop->high_PHY_capable = device_property_read_bool(dev,
 322                         "mipi-sdw-highPHY-capable");
 323 
 324         prop->paging_support = device_property_read_bool(dev,
 325                         "mipi-sdw-paging-support");
 326 
 327         prop->bank_delay_support = device_property_read_bool(dev,
 328                         "mipi-sdw-bank-delay-support");
 329 
 330         device_property_read_u32(dev,
 331                         "mipi-sdw-port15-read-behavior", &prop->p15_behave);
 332 
 333         device_property_read_u32(dev, "mipi-sdw-master-count",
 334                                  &prop->master_count);
 335 
 336         device_property_read_u32(dev, "mipi-sdw-source-port-list",
 337                                  &prop->source_ports);
 338 
 339         device_property_read_u32(dev, "mipi-sdw-sink-port-list",
 340                                  &prop->sink_ports);
 341 
 342         /* Read dp0 properties */
 343         port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
 344         if (!port) {
 345                 dev_dbg(dev, "DP0 node not found!!\n");
 346         } else {
 347                 prop->dp0_prop = devm_kzalloc(&slave->dev,
 348                                               sizeof(*prop->dp0_prop),
 349                                               GFP_KERNEL);
 350                 if (!prop->dp0_prop)
 351                         return -ENOMEM;
 352 
 353                 sdw_slave_read_dp0(slave, port, prop->dp0_prop);
 354                 dp0 = 1;
 355         }
 356 
 357         /*
 358          * Based on each DPn port, get source and sink dpn properties.
 359          * Also, some ports can operate as both source or sink.
 360          */
 361 
 362         /* Allocate memory for set bits in port lists */
 363         nval = hweight32(prop->source_ports);
 364         prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
 365                                           sizeof(*prop->src_dpn_prop),
 366                                           GFP_KERNEL);
 367         if (!prop->src_dpn_prop)
 368                 return -ENOMEM;
 369 
 370         /* Read dpn properties for source port(s) */
 371         sdw_slave_read_dpn(slave, prop->src_dpn_prop, nval,
 372                            prop->source_ports, "source");
 373 
 374         nval = hweight32(prop->sink_ports);
 375         prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
 376                                            sizeof(*prop->sink_dpn_prop),
 377                                            GFP_KERNEL);
 378         if (!prop->sink_dpn_prop)
 379                 return -ENOMEM;
 380 
 381         /* Read dpn properties for sink port(s) */
 382         sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval,
 383                            prop->sink_ports, "sink");
 384 
 385         /* some ports are bidirectional so check total ports by ORing */
 386         nval = prop->source_ports | prop->sink_ports;
 387         num_of_ports = hweight32(nval) + dp0; /* add DP0 */
 388 
 389         /* Allocate port_ready based on num_of_ports */
 390         slave->port_ready = devm_kcalloc(&slave->dev, num_of_ports,
 391                                          sizeof(*slave->port_ready),
 392                                          GFP_KERNEL);
 393         if (!slave->port_ready)
 394                 return -ENOMEM;
 395 
 396         /* Initialize completion */
 397         for (i = 0; i < num_of_ports; i++)
 398                 init_completion(&slave->port_ready[i]);
 399 
 400         return 0;
 401 }
 402 EXPORT_SYMBOL(sdw_slave_read_prop);

/* [<][>][^][v][top][bottom][index][help] */