linux/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
<<
>>
Prefs
   1/*
   2 * Copyright 2018 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include <linux/delay.h>
  27
  28#include "dce_i2c.h"
  29#include "dce_i2c_sw.h"
  30#include "include/gpio_service_interface.h"
  31#define SCL false
  32#define SDA true
  33
  34void dce_i2c_sw_construct(
  35        struct dce_i2c_sw *dce_i2c_sw,
  36        struct dc_context *ctx)
  37{
  38        dce_i2c_sw->ctx = ctx;
  39}
  40
  41static inline bool read_bit_from_ddc(
  42        struct ddc *ddc,
  43        bool data_nor_clock)
  44{
  45        uint32_t value = 0;
  46
  47        if (data_nor_clock)
  48                dal_gpio_get_value(ddc->pin_data, &value);
  49        else
  50                dal_gpio_get_value(ddc->pin_clock, &value);
  51
  52        return (value != 0);
  53}
  54
  55static inline void write_bit_to_ddc(
  56        struct ddc *ddc,
  57        bool data_nor_clock,
  58        bool bit)
  59{
  60        uint32_t value = bit ? 1 : 0;
  61
  62        if (data_nor_clock)
  63                dal_gpio_set_value(ddc->pin_data, value);
  64        else
  65                dal_gpio_set_value(ddc->pin_clock, value);
  66}
  67
  68static void release_engine_dce_sw(
  69        struct resource_pool *pool,
  70        struct dce_i2c_sw *dce_i2c_sw)
  71{
  72        dal_ddc_close(dce_i2c_sw->ddc);
  73        dce_i2c_sw->ddc = NULL;
  74}
  75
  76static bool get_hw_supported_ddc_line(
  77        struct ddc *ddc,
  78        enum gpio_ddc_line *line)
  79{
  80        enum gpio_ddc_line line_found;
  81
  82        *line = GPIO_DDC_LINE_UNKNOWN;
  83
  84        if (!ddc) {
  85                BREAK_TO_DEBUGGER();
  86                return false;
  87        }
  88
  89        if (!ddc->hw_info.hw_supported)
  90                return false;
  91
  92        line_found = dal_ddc_get_line(ddc);
  93
  94        if (line_found >= GPIO_DDC_LINE_COUNT)
  95                return false;
  96
  97        *line = line_found;
  98
  99        return true;
 100}
 101static bool wait_for_scl_high_sw(
 102        struct dc_context *ctx,
 103        struct ddc *ddc,
 104        uint16_t clock_delay_div_4)
 105{
 106        uint32_t scl_retry = 0;
 107        uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
 108
 109        udelay(clock_delay_div_4);
 110
 111        do {
 112                if (read_bit_from_ddc(ddc, SCL))
 113                        return true;
 114
 115                udelay(clock_delay_div_4);
 116
 117                ++scl_retry;
 118        } while (scl_retry <= scl_retry_max);
 119
 120        return false;
 121}
 122static bool write_byte_sw(
 123        struct dc_context *ctx,
 124        struct ddc *ddc_handle,
 125        uint16_t clock_delay_div_4,
 126        uint8_t byte)
 127{
 128        int32_t shift = 7;
 129        bool ack;
 130
 131        /* bits are transmitted serially, starting from MSB */
 132
 133        do {
 134                udelay(clock_delay_div_4);
 135
 136                write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
 137
 138                udelay(clock_delay_div_4);
 139
 140                write_bit_to_ddc(ddc_handle, SCL, true);
 141
 142                if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
 143                        return false;
 144
 145                write_bit_to_ddc(ddc_handle, SCL, false);
 146
 147                --shift;
 148        } while (shift >= 0);
 149
 150        /* The display sends ACK by preventing the SDA from going high
 151         * after the SCL pulse we use to send our last data bit.
 152         * If the SDA goes high after that bit, it's a NACK
 153         */
 154
 155        udelay(clock_delay_div_4);
 156
 157        write_bit_to_ddc(ddc_handle, SDA, true);
 158
 159        udelay(clock_delay_div_4);
 160
 161        write_bit_to_ddc(ddc_handle, SCL, true);
 162
 163        if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
 164                return false;
 165
 166        /* read ACK bit */
 167
 168        ack = !read_bit_from_ddc(ddc_handle, SDA);
 169
 170        udelay(clock_delay_div_4 << 1);
 171
 172        write_bit_to_ddc(ddc_handle, SCL, false);
 173
 174        udelay(clock_delay_div_4 << 1);
 175
 176        return ack;
 177}
 178
 179static bool read_byte_sw(
 180        struct dc_context *ctx,
 181        struct ddc *ddc_handle,
 182        uint16_t clock_delay_div_4,
 183        uint8_t *byte,
 184        bool more)
 185{
 186        int32_t shift = 7;
 187
 188        uint8_t data = 0;
 189
 190        /* The data bits are read from MSB to LSB;
 191         * bit is read while SCL is high
 192         */
 193
 194        do {
 195                write_bit_to_ddc(ddc_handle, SCL, true);
 196
 197                if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
 198                        return false;
 199
 200                if (read_bit_from_ddc(ddc_handle, SDA))
 201                        data |= (1 << shift);
 202
 203                write_bit_to_ddc(ddc_handle, SCL, false);
 204
 205                udelay(clock_delay_div_4 << 1);
 206
 207                --shift;
 208        } while (shift >= 0);
 209
 210        /* read only whole byte */
 211
 212        *byte = data;
 213
 214        udelay(clock_delay_div_4);
 215
 216        /* send the acknowledge bit:
 217         * SDA low means ACK, SDA high means NACK
 218         */
 219
 220        write_bit_to_ddc(ddc_handle, SDA, !more);
 221
 222        udelay(clock_delay_div_4);
 223
 224        write_bit_to_ddc(ddc_handle, SCL, true);
 225
 226        if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
 227                return false;
 228
 229        write_bit_to_ddc(ddc_handle, SCL, false);
 230
 231        udelay(clock_delay_div_4);
 232
 233        write_bit_to_ddc(ddc_handle, SDA, true);
 234
 235        udelay(clock_delay_div_4);
 236
 237        return true;
 238}
 239static bool stop_sync_sw(
 240        struct dc_context *ctx,
 241        struct ddc *ddc_handle,
 242        uint16_t clock_delay_div_4)
 243{
 244        uint32_t retry = 0;
 245
 246        /* The I2C communications stop signal is:
 247         * the SDA going high from low, while the SCL is high.
 248         */
 249
 250        write_bit_to_ddc(ddc_handle, SCL, false);
 251
 252        udelay(clock_delay_div_4);
 253
 254        write_bit_to_ddc(ddc_handle, SDA, false);
 255
 256        udelay(clock_delay_div_4);
 257
 258        write_bit_to_ddc(ddc_handle, SCL, true);
 259
 260        if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
 261                return false;
 262
 263        write_bit_to_ddc(ddc_handle, SDA, true);
 264
 265        do {
 266                udelay(clock_delay_div_4);
 267
 268                if (read_bit_from_ddc(ddc_handle, SDA))
 269                        return true;
 270
 271                ++retry;
 272        } while (retry <= 2);
 273
 274        return false;
 275}
 276static bool i2c_write_sw(
 277        struct dc_context *ctx,
 278        struct ddc *ddc_handle,
 279        uint16_t clock_delay_div_4,
 280        uint8_t address,
 281        uint32_t length,
 282        const uint8_t *data)
 283{
 284        uint32_t i = 0;
 285
 286        if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
 287                return false;
 288
 289        while (i < length) {
 290                if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
 291                        return false;
 292                ++i;
 293        }
 294
 295        return true;
 296}
 297
 298static bool i2c_read_sw(
 299        struct dc_context *ctx,
 300        struct ddc *ddc_handle,
 301        uint16_t clock_delay_div_4,
 302        uint8_t address,
 303        uint32_t length,
 304        uint8_t *data)
 305{
 306        uint32_t i = 0;
 307
 308        if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
 309                return false;
 310
 311        while (i < length) {
 312                if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
 313                        i < length - 1))
 314                        return false;
 315                ++i;
 316        }
 317
 318        return true;
 319}
 320
 321
 322
 323static bool start_sync_sw(
 324        struct dc_context *ctx,
 325        struct ddc *ddc_handle,
 326        uint16_t clock_delay_div_4)
 327{
 328        uint32_t retry = 0;
 329
 330        /* The I2C communications start signal is:
 331         * the SDA going low from high, while the SCL is high.
 332         */
 333
 334        write_bit_to_ddc(ddc_handle, SCL, true);
 335
 336        udelay(clock_delay_div_4);
 337
 338        do {
 339                write_bit_to_ddc(ddc_handle, SDA, true);
 340
 341                if (!read_bit_from_ddc(ddc_handle, SDA)) {
 342                        ++retry;
 343                        continue;
 344                }
 345
 346                udelay(clock_delay_div_4);
 347
 348                write_bit_to_ddc(ddc_handle, SCL, true);
 349
 350                if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
 351                        break;
 352
 353                write_bit_to_ddc(ddc_handle, SDA, false);
 354
 355                udelay(clock_delay_div_4);
 356
 357                write_bit_to_ddc(ddc_handle, SCL, false);
 358
 359                udelay(clock_delay_div_4);
 360
 361                return true;
 362        } while (retry <= I2C_SW_RETRIES);
 363
 364        return false;
 365}
 366
 367void dce_i2c_sw_engine_set_speed(
 368        struct dce_i2c_sw *engine,
 369        uint32_t speed)
 370{
 371        ASSERT(speed);
 372
 373        engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
 374
 375        engine->clock_delay = 1000 / engine->speed;
 376
 377        if (engine->clock_delay < 12)
 378                engine->clock_delay = 12;
 379}
 380
 381bool dce_i2c_sw_engine_acquire_engine(
 382        struct dce_i2c_sw *engine,
 383        struct ddc *ddc)
 384{
 385        enum gpio_result result;
 386
 387        result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
 388                GPIO_DDC_CONFIG_TYPE_MODE_I2C);
 389
 390        if (result != GPIO_RESULT_OK)
 391                return false;
 392
 393        engine->ddc = ddc;
 394
 395        return true;
 396}
 397bool dce_i2c_engine_acquire_sw(
 398        struct dce_i2c_sw *dce_i2c_sw,
 399        struct ddc *ddc_handle)
 400{
 401        uint32_t counter = 0;
 402        bool result;
 403
 404        do {
 405
 406                result = dce_i2c_sw_engine_acquire_engine(
 407                                dce_i2c_sw, ddc_handle);
 408
 409                if (result)
 410                        break;
 411
 412                /* i2c_engine is busy by VBios, lets wait and retry */
 413
 414                udelay(10);
 415
 416                ++counter;
 417        } while (counter < 2);
 418
 419        return result;
 420}
 421
 422
 423
 424
 425void dce_i2c_sw_engine_submit_channel_request(
 426        struct dce_i2c_sw *engine,
 427        struct i2c_request_transaction_data *req)
 428{
 429        struct ddc *ddc = engine->ddc;
 430        uint16_t clock_delay_div_4 = engine->clock_delay >> 2;
 431
 432        /* send sync (start / repeated start) */
 433
 434        bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
 435
 436        /* process payload */
 437
 438        if (result) {
 439                switch (req->action) {
 440                case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
 441                case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
 442                        result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
 443                                req->address, req->length, req->data);
 444                break;
 445                case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
 446                case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
 447                        result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
 448                                req->address, req->length, req->data);
 449                break;
 450                default:
 451                        result = false;
 452                break;
 453                }
 454        }
 455
 456        /* send stop if not 'mot' or operation failed */
 457
 458        if (!result ||
 459                (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
 460                (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
 461                if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
 462                        result = false;
 463
 464        req->status = result ?
 465                I2C_CHANNEL_OPERATION_SUCCEEDED :
 466                I2C_CHANNEL_OPERATION_FAILED;
 467}
 468bool dce_i2c_sw_engine_submit_payload(
 469        struct dce_i2c_sw *engine,
 470        struct i2c_payload *payload,
 471        bool middle_of_transaction)
 472{
 473        struct i2c_request_transaction_data request;
 474
 475        if (!payload->write)
 476                request.action = middle_of_transaction ?
 477                        DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
 478                        DCE_I2C_TRANSACTION_ACTION_I2C_READ;
 479        else
 480                request.action = middle_of_transaction ?
 481                        DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
 482                        DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
 483
 484        request.address = (uint8_t) ((payload->address << 1) | !payload->write);
 485        request.length = payload->length;
 486        request.data = payload->data;
 487
 488        dce_i2c_sw_engine_submit_channel_request(engine, &request);
 489
 490        if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
 491                (request.status == I2C_CHANNEL_OPERATION_FAILED))
 492                return false;
 493
 494        return true;
 495}
 496bool dce_i2c_submit_command_sw(
 497        struct resource_pool *pool,
 498        struct ddc *ddc,
 499        struct i2c_command *cmd,
 500        struct dce_i2c_sw *dce_i2c_sw)
 501{
 502        uint8_t index_of_payload = 0;
 503        bool result;
 504
 505        dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
 506
 507        result = true;
 508
 509        while (index_of_payload < cmd->number_of_payloads) {
 510                bool mot = (index_of_payload != cmd->number_of_payloads - 1);
 511
 512                struct i2c_payload *payload = cmd->payloads + index_of_payload;
 513
 514                if (!dce_i2c_sw_engine_submit_payload(
 515                        dce_i2c_sw, payload, mot)) {
 516                        result = false;
 517                        break;
 518                }
 519
 520                ++index_of_payload;
 521        }
 522
 523        release_engine_dce_sw(pool, dce_i2c_sw);
 524
 525        return result;
 526}
 527struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine(
 528        struct resource_pool *pool,
 529        struct ddc *ddc)
 530{
 531        enum gpio_ddc_line line;
 532        struct dce_i2c_sw *engine = NULL;
 533
 534        if (get_hw_supported_ddc_line(ddc, &line))
 535                engine = pool->sw_i2cs[line];
 536
 537        if (!engine)
 538                return NULL;
 539
 540        if (!dce_i2c_engine_acquire_sw(engine, ddc))
 541                return NULL;
 542
 543        return engine;
 544}
 545