linux/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
<<
>>
Prefs
   1/*
   2 * Copyright 2015 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/irqdomain.h>
  27#include <linux/pci.h>
  28#include <linux/pm_domain.h>
  29#include <linux/platform_device.h>
  30#include <sound/designware_i2s.h>
  31#include <sound/pcm.h>
  32
  33#include "amdgpu.h"
  34#include "atom.h"
  35#include "amdgpu_acp.h"
  36
  37#include "acp_gfx_if.h"
  38
  39#define ACP_TILE_ON_MASK                        0x03
  40#define ACP_TILE_OFF_MASK                       0x02
  41#define ACP_TILE_ON_RETAIN_REG_MASK             0x1f
  42#define ACP_TILE_OFF_RETAIN_REG_MASK            0x20
  43
  44#define ACP_TILE_P1_MASK                        0x3e
  45#define ACP_TILE_P2_MASK                        0x3d
  46#define ACP_TILE_DSP0_MASK                      0x3b
  47#define ACP_TILE_DSP1_MASK                      0x37
  48
  49#define ACP_TILE_DSP2_MASK                      0x2f
  50
  51#define ACP_DMA_REGS_END                        0x146c0
  52#define ACP_I2S_PLAY_REGS_START                 0x14840
  53#define ACP_I2S_PLAY_REGS_END                   0x148b4
  54#define ACP_I2S_CAP_REGS_START                  0x148b8
  55#define ACP_I2S_CAP_REGS_END                    0x1496c
  56
  57#define ACP_I2S_COMP1_CAP_REG_OFFSET            0xac
  58#define ACP_I2S_COMP2_CAP_REG_OFFSET            0xa8
  59#define ACP_I2S_COMP1_PLAY_REG_OFFSET           0x6c
  60#define ACP_I2S_COMP2_PLAY_REG_OFFSET           0x68
  61#define ACP_BT_PLAY_REGS_START                  0x14970
  62#define ACP_BT_PLAY_REGS_END                    0x14a24
  63#define ACP_BT_COMP1_REG_OFFSET                 0xac
  64#define ACP_BT_COMP2_REG_OFFSET                 0xa8
  65
  66#define mmACP_PGFSM_RETAIN_REG                  0x51c9
  67#define mmACP_PGFSM_CONFIG_REG                  0x51ca
  68#define mmACP_PGFSM_READ_REG_0                  0x51cc
  69
  70#define mmACP_MEM_SHUT_DOWN_REQ_LO              0x51f8
  71#define mmACP_MEM_SHUT_DOWN_REQ_HI              0x51f9
  72#define mmACP_MEM_SHUT_DOWN_STS_LO              0x51fa
  73#define mmACP_MEM_SHUT_DOWN_STS_HI              0x51fb
  74
  75#define mmACP_CONTROL                           0x5131
  76#define mmACP_STATUS                            0x5133
  77#define mmACP_SOFT_RESET                        0x5134
  78#define ACP_CONTROL__ClkEn_MASK                 0x1
  79#define ACP_SOFT_RESET__SoftResetAud_MASK       0x100
  80#define ACP_SOFT_RESET__SoftResetAudDone_MASK   0x1000000
  81#define ACP_CLOCK_EN_TIME_OUT_VALUE             0x000000FF
  82#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE      0x000000FF
  83
  84#define ACP_TIMEOUT_LOOP                        0x000000FF
  85#define ACP_DEVS                                4
  86#define ACP_SRC_ID                              162
  87
  88enum {
  89        ACP_TILE_P1 = 0,
  90        ACP_TILE_P2,
  91        ACP_TILE_DSP0,
  92        ACP_TILE_DSP1,
  93        ACP_TILE_DSP2,
  94};
  95
  96static int acp_sw_init(void *handle)
  97{
  98        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  99
 100        adev->acp.parent = adev->dev;
 101
 102        adev->acp.cgs_device =
 103                amdgpu_cgs_create_device(adev);
 104        if (!adev->acp.cgs_device)
 105                return -EINVAL;
 106
 107        return 0;
 108}
 109
 110static int acp_sw_fini(void *handle)
 111{
 112        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 113
 114        if (adev->acp.cgs_device)
 115                amdgpu_cgs_destroy_device(adev->acp.cgs_device);
 116
 117        return 0;
 118}
 119
 120struct acp_pm_domain {
 121        void *adev;
 122        struct generic_pm_domain gpd;
 123};
 124
 125static int acp_poweroff(struct generic_pm_domain *genpd)
 126{
 127        struct acp_pm_domain *apd;
 128        struct amdgpu_device *adev;
 129
 130        apd = container_of(genpd, struct acp_pm_domain, gpd);
 131        if (apd != NULL) {
 132                adev = apd->adev;
 133        /* call smu to POWER GATE ACP block
 134         * smu will
 135         * 1. turn off the acp clock
 136         * 2. power off the acp tiles
 137         * 3. check and enter ulv state
 138         */
 139                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
 140        }
 141        return 0;
 142}
 143
 144static int acp_poweron(struct generic_pm_domain *genpd)
 145{
 146        struct acp_pm_domain *apd;
 147        struct amdgpu_device *adev;
 148
 149        apd = container_of(genpd, struct acp_pm_domain, gpd);
 150        if (apd != NULL) {
 151                adev = apd->adev;
 152        /* call smu to UNGATE ACP block
 153         * smu will
 154         * 1. exit ulv
 155         * 2. turn on acp clock
 156         * 3. power on acp tiles
 157         */
 158                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
 159        }
 160        return 0;
 161}
 162
 163static int acp_genpd_add_device(struct device *dev, void *data)
 164{
 165        struct generic_pm_domain *gpd = data;
 166        int ret;
 167
 168        ret = pm_genpd_add_device(gpd, dev);
 169        if (ret)
 170                dev_err(dev, "Failed to add dev to genpd %d\n", ret);
 171
 172        return ret;
 173}
 174
 175static int acp_genpd_remove_device(struct device *dev, void *data)
 176{
 177        int ret;
 178
 179        ret = pm_genpd_remove_device(dev);
 180        if (ret)
 181                dev_err(dev, "Failed to remove dev from genpd %d\n", ret);
 182
 183        /* Continue to remove */
 184        return 0;
 185}
 186
 187/**
 188 * acp_hw_init - start and test ACP block
 189 *
 190 * @handle: handle used to pass amdgpu_device pointer
 191 *
 192 */
 193static int acp_hw_init(void *handle)
 194{
 195        int r;
 196        uint64_t acp_base;
 197        u32 val = 0;
 198        u32 count = 0;
 199        struct i2s_platform_data *i2s_pdata = NULL;
 200
 201        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 202
 203        const struct amdgpu_ip_block *ip_block =
 204                amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ACP);
 205
 206        if (!ip_block)
 207                return -EINVAL;
 208
 209        r = amd_acp_hw_init(adev->acp.cgs_device,
 210                            ip_block->version->major, ip_block->version->minor);
 211        /* -ENODEV means board uses AZ rather than ACP */
 212        if (r == -ENODEV) {
 213                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
 214                return 0;
 215        } else if (r) {
 216                return r;
 217        }
 218
 219        if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
 220                return -EINVAL;
 221
 222        acp_base = adev->rmmio_base;
 223
 224
 225        adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL);
 226        if (adev->acp.acp_genpd == NULL)
 227                return -ENOMEM;
 228
 229        adev->acp.acp_genpd->gpd.name = "ACP_AUDIO";
 230        adev->acp.acp_genpd->gpd.power_off = acp_poweroff;
 231        adev->acp.acp_genpd->gpd.power_on = acp_poweron;
 232
 233
 234        adev->acp.acp_genpd->adev = adev;
 235
 236        pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
 237
 238        adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
 239                                                        GFP_KERNEL);
 240
 241        if (adev->acp.acp_cell == NULL) {
 242                r = -ENOMEM;
 243                goto failure;
 244        }
 245
 246        adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL);
 247        if (adev->acp.acp_res == NULL) {
 248                r = -ENOMEM;
 249                goto failure;
 250        }
 251
 252        i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL);
 253        if (i2s_pdata == NULL) {
 254                r = -ENOMEM;
 255                goto failure;
 256        }
 257
 258        switch (adev->asic_type) {
 259        case CHIP_STONEY:
 260                i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
 261                        DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
 262                break;
 263        default:
 264                i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
 265        }
 266        i2s_pdata[0].cap = DWC_I2S_PLAY;
 267        i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000;
 268        i2s_pdata[0].i2s_reg_comp1 = ACP_I2S_COMP1_PLAY_REG_OFFSET;
 269        i2s_pdata[0].i2s_reg_comp2 = ACP_I2S_COMP2_PLAY_REG_OFFSET;
 270        switch (adev->asic_type) {
 271        case CHIP_STONEY:
 272                i2s_pdata[1].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
 273                        DW_I2S_QUIRK_COMP_PARAM1 |
 274                        DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
 275                break;
 276        default:
 277                i2s_pdata[1].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
 278                        DW_I2S_QUIRK_COMP_PARAM1;
 279        }
 280
 281        i2s_pdata[1].cap = DWC_I2S_RECORD;
 282        i2s_pdata[1].snd_rates = SNDRV_PCM_RATE_8000_96000;
 283        i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
 284        i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
 285
 286        i2s_pdata[2].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
 287        switch (adev->asic_type) {
 288        case CHIP_STONEY:
 289                i2s_pdata[2].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
 290                break;
 291        default:
 292                break;
 293        }
 294
 295        i2s_pdata[2].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
 296        i2s_pdata[2].snd_rates = SNDRV_PCM_RATE_8000_96000;
 297        i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET;
 298        i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET;
 299
 300        adev->acp.acp_res[0].name = "acp2x_dma";
 301        adev->acp.acp_res[0].flags = IORESOURCE_MEM;
 302        adev->acp.acp_res[0].start = acp_base;
 303        adev->acp.acp_res[0].end = acp_base + ACP_DMA_REGS_END;
 304
 305        adev->acp.acp_res[1].name = "acp2x_dw_i2s_play";
 306        adev->acp.acp_res[1].flags = IORESOURCE_MEM;
 307        adev->acp.acp_res[1].start = acp_base + ACP_I2S_PLAY_REGS_START;
 308        adev->acp.acp_res[1].end = acp_base + ACP_I2S_PLAY_REGS_END;
 309
 310        adev->acp.acp_res[2].name = "acp2x_dw_i2s_cap";
 311        adev->acp.acp_res[2].flags = IORESOURCE_MEM;
 312        adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START;
 313        adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END;
 314
 315        adev->acp.acp_res[3].name = "acp2x_dw_bt_i2s_play_cap";
 316        adev->acp.acp_res[3].flags = IORESOURCE_MEM;
 317        adev->acp.acp_res[3].start = acp_base + ACP_BT_PLAY_REGS_START;
 318        adev->acp.acp_res[3].end = acp_base + ACP_BT_PLAY_REGS_END;
 319
 320        adev->acp.acp_res[4].name = "acp2x_dma_irq";
 321        adev->acp.acp_res[4].flags = IORESOURCE_IRQ;
 322        adev->acp.acp_res[4].start = amdgpu_irq_create_mapping(adev, 162);
 323        adev->acp.acp_res[4].end = adev->acp.acp_res[4].start;
 324
 325        adev->acp.acp_cell[0].name = "acp_audio_dma";
 326        adev->acp.acp_cell[0].num_resources = 5;
 327        adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
 328        adev->acp.acp_cell[0].platform_data = &adev->asic_type;
 329        adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
 330
 331        adev->acp.acp_cell[1].name = "designware-i2s";
 332        adev->acp.acp_cell[1].num_resources = 1;
 333        adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1];
 334        adev->acp.acp_cell[1].platform_data = &i2s_pdata[0];
 335        adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data);
 336
 337        adev->acp.acp_cell[2].name = "designware-i2s";
 338        adev->acp.acp_cell[2].num_resources = 1;
 339        adev->acp.acp_cell[2].resources = &adev->acp.acp_res[2];
 340        adev->acp.acp_cell[2].platform_data = &i2s_pdata[1];
 341        adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data);
 342
 343        adev->acp.acp_cell[3].name = "designware-i2s";
 344        adev->acp.acp_cell[3].num_resources = 1;
 345        adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3];
 346        adev->acp.acp_cell[3].platform_data = &i2s_pdata[2];
 347        adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data);
 348
 349        r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell,
 350                                                                ACP_DEVS);
 351        if (r)
 352                goto failure;
 353
 354        r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
 355                                  acp_genpd_add_device);
 356        if (r)
 357                goto failure;
 358
 359        /* Assert Soft reset of ACP */
 360        val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
 361
 362        val |= ACP_SOFT_RESET__SoftResetAud_MASK;
 363        cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
 364
 365        count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
 366        while (true) {
 367                val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
 368                if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
 369                    (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
 370                        break;
 371                if (--count == 0) {
 372                        dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
 373                        r = -ETIMEDOUT;
 374                        goto failure;
 375                }
 376                udelay(100);
 377        }
 378        /* Enable clock to ACP and wait until the clock is enabled */
 379        val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL);
 380        val = val | ACP_CONTROL__ClkEn_MASK;
 381        cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val);
 382
 383        count = ACP_CLOCK_EN_TIME_OUT_VALUE;
 384
 385        while (true) {
 386                val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS);
 387                if (val & (u32) 0x1)
 388                        break;
 389                if (--count == 0) {
 390                        dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
 391                        r = -ETIMEDOUT;
 392                        goto failure;
 393                }
 394                udelay(100);
 395        }
 396        /* Deassert the SOFT RESET flags */
 397        val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
 398        val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
 399        cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
 400        return 0;
 401
 402failure:
 403        kfree(i2s_pdata);
 404        kfree(adev->acp.acp_res);
 405        kfree(adev->acp.acp_cell);
 406        kfree(adev->acp.acp_genpd);
 407        return r;
 408}
 409
 410/**
 411 * acp_hw_fini - stop the hardware block
 412 *
 413 * @handle: handle used to pass amdgpu_device pointer
 414 *
 415 */
 416static int acp_hw_fini(void *handle)
 417{
 418        u32 val = 0;
 419        u32 count = 0;
 420        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 421
 422        /* return early if no ACP */
 423        if (!adev->acp.acp_genpd) {
 424                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
 425                return 0;
 426        }
 427
 428        /* Assert Soft reset of ACP */
 429        val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
 430
 431        val |= ACP_SOFT_RESET__SoftResetAud_MASK;
 432        cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
 433
 434        count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
 435        while (true) {
 436                val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
 437                if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
 438                    (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
 439                        break;
 440                if (--count == 0) {
 441                        dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
 442                        return -ETIMEDOUT;
 443                }
 444                udelay(100);
 445        }
 446        /* Disable ACP clock */
 447        val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL);
 448        val &= ~ACP_CONTROL__ClkEn_MASK;
 449        cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val);
 450
 451        count = ACP_CLOCK_EN_TIME_OUT_VALUE;
 452
 453        while (true) {
 454                val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS);
 455                if (val & (u32) 0x1)
 456                        break;
 457                if (--count == 0) {
 458                        dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
 459                        return -ETIMEDOUT;
 460                }
 461                udelay(100);
 462        }
 463
 464        device_for_each_child(adev->acp.parent, NULL,
 465                              acp_genpd_remove_device);
 466
 467        mfd_remove_devices(adev->acp.parent);
 468        kfree(adev->acp.acp_res);
 469        kfree(adev->acp.acp_genpd);
 470        kfree(adev->acp.acp_cell);
 471
 472        return 0;
 473}
 474
 475static int acp_suspend(void *handle)
 476{
 477        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 478
 479        /* power up on suspend */
 480        if (!adev->acp.acp_cell)
 481                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
 482        return 0;
 483}
 484
 485static int acp_resume(void *handle)
 486{
 487        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 488
 489        /* power down again on resume */
 490        if (!adev->acp.acp_cell)
 491                amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
 492        return 0;
 493}
 494
 495static int acp_early_init(void *handle)
 496{
 497        return 0;
 498}
 499
 500static bool acp_is_idle(void *handle)
 501{
 502        return true;
 503}
 504
 505static int acp_wait_for_idle(void *handle)
 506{
 507        return 0;
 508}
 509
 510static int acp_soft_reset(void *handle)
 511{
 512        return 0;
 513}
 514
 515static int acp_set_clockgating_state(void *handle,
 516                                     enum amd_clockgating_state state)
 517{
 518        return 0;
 519}
 520
 521static int acp_set_powergating_state(void *handle,
 522                                     enum amd_powergating_state state)
 523{
 524        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 525        bool enable = (state == AMD_PG_STATE_GATE);
 526
 527        amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable);
 528
 529        return 0;
 530}
 531
 532static const struct amd_ip_funcs acp_ip_funcs = {
 533        .name = "acp_ip",
 534        .early_init = acp_early_init,
 535        .late_init = NULL,
 536        .sw_init = acp_sw_init,
 537        .sw_fini = acp_sw_fini,
 538        .hw_init = acp_hw_init,
 539        .hw_fini = acp_hw_fini,
 540        .suspend = acp_suspend,
 541        .resume = acp_resume,
 542        .is_idle = acp_is_idle,
 543        .wait_for_idle = acp_wait_for_idle,
 544        .soft_reset = acp_soft_reset,
 545        .set_clockgating_state = acp_set_clockgating_state,
 546        .set_powergating_state = acp_set_powergating_state,
 547};
 548
 549const struct amdgpu_ip_block_version acp_ip_block =
 550{
 551        .type = AMD_IP_BLOCK_TYPE_ACP,
 552        .major = 2,
 553        .minor = 2,
 554        .rev = 0,
 555        .funcs = &acp_ip_funcs,
 556};
 557