0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/slab.h>
0010 #include <linux/export.h>
0011 #include <sound/core.h>
0012 #include <sound/control.h>
0013 #include <sound/jack.h>
0014 #include <sound/hda_codec.h>
0015 #include "hda_local.h"
0016 #include "hda_auto_parser.h"
0017 #include "hda_jack.h"
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
0030 {
0031 if (codec->no_jack_detect)
0032 return false;
0033 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
0034 return false;
0035 if (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
0036 AC_DEFCFG_MISC_NO_PRESENCE)
0037 return false;
0038 if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) &&
0039 !codec->jackpoll_interval)
0040 return false;
0041 return true;
0042 }
0043 EXPORT_SYMBOL_GPL(is_jack_detectable);
0044
0045
0046 static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
0047 {
0048 u32 pincap;
0049 u32 val;
0050
0051 if (!codec->no_trigger_sense) {
0052 pincap = snd_hda_query_pin_caps(codec, nid);
0053 if (pincap & AC_PINCAP_TRIG_REQ)
0054 snd_hda_codec_read(codec, nid, 0,
0055 AC_VERB_SET_PIN_SENSE, 0);
0056 }
0057 val = snd_hda_codec_read(codec, nid, 0,
0058 AC_VERB_GET_PIN_SENSE, dev_id);
0059 if (codec->inv_jack_detect)
0060 val ^= AC_PINSENSE_PRESENCE;
0061 return val;
0062 }
0063
0064
0065
0066
0067
0068
0069
0070 struct hda_jack_tbl *
0071 snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id)
0072 {
0073 struct hda_jack_tbl *jack = codec->jacktbl.list;
0074 int i;
0075
0076 if (!nid || !jack)
0077 return NULL;
0078 for (i = 0; i < codec->jacktbl.used; i++, jack++)
0079 if (jack->nid == nid && jack->dev_id == dev_id)
0080 return jack;
0081 return NULL;
0082 }
0083 EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_mst);
0084
0085
0086
0087
0088
0089
0090
0091 struct hda_jack_tbl *
0092 snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
0093 unsigned char tag, int dev_id)
0094 {
0095 struct hda_jack_tbl *jack = codec->jacktbl.list;
0096 int i;
0097
0098 if (!tag || !jack)
0099 return NULL;
0100 for (i = 0; i < codec->jacktbl.used; i++, jack++)
0101 if (jack->tag == tag && jack->dev_id == dev_id)
0102 return jack;
0103 return NULL;
0104 }
0105 EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
0106
0107 static struct hda_jack_tbl *
0108 any_jack_tbl_get_from_nid(struct hda_codec *codec, hda_nid_t nid)
0109 {
0110 struct hda_jack_tbl *jack = codec->jacktbl.list;
0111 int i;
0112
0113 if (!nid || !jack)
0114 return NULL;
0115 for (i = 0; i < codec->jacktbl.used; i++, jack++)
0116 if (jack->nid == nid)
0117 return jack;
0118 return NULL;
0119 }
0120
0121
0122
0123
0124
0125
0126
0127 static struct hda_jack_tbl *
0128 snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id)
0129 {
0130 struct hda_jack_tbl *jack =
0131 snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
0132 struct hda_jack_tbl *existing_nid_jack =
0133 any_jack_tbl_get_from_nid(codec, nid);
0134
0135 WARN_ON(dev_id != 0 && !codec->dp_mst);
0136
0137 if (jack)
0138 return jack;
0139 jack = snd_array_new(&codec->jacktbl);
0140 if (!jack)
0141 return NULL;
0142 jack->nid = nid;
0143 jack->dev_id = dev_id;
0144 jack->jack_dirty = 1;
0145 if (existing_nid_jack) {
0146 jack->tag = existing_nid_jack->tag;
0147
0148
0149
0150
0151
0152
0153 jack->jack_detect = existing_nid_jack->jack_detect;
0154 } else {
0155 jack->tag = codec->jacktbl.used;
0156 }
0157
0158 return jack;
0159 }
0160
0161 void snd_hda_jack_tbl_disconnect(struct hda_codec *codec)
0162 {
0163 struct hda_jack_tbl *jack = codec->jacktbl.list;
0164 int i;
0165
0166 for (i = 0; i < codec->jacktbl.used; i++, jack++) {
0167 if (!codec->bus->shutdown && jack->jack)
0168 snd_device_disconnect(codec->card, jack->jack);
0169 }
0170 }
0171
0172 void snd_hda_jack_tbl_clear(struct hda_codec *codec)
0173 {
0174 struct hda_jack_tbl *jack = codec->jacktbl.list;
0175 int i;
0176
0177 for (i = 0; i < codec->jacktbl.used; i++, jack++) {
0178 struct hda_jack_callback *cb, *next;
0179
0180
0181 if (!codec->bus->shutdown && jack->jack)
0182 snd_device_free(codec->card, jack->jack);
0183
0184 for (cb = jack->callback; cb; cb = next) {
0185 next = cb->next;
0186 kfree(cb);
0187 }
0188 }
0189 snd_array_free(&codec->jacktbl);
0190 }
0191
0192 #define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
0193
0194
0195 static void jack_detect_update(struct hda_codec *codec,
0196 struct hda_jack_tbl *jack)
0197 {
0198 if (!jack->jack_dirty)
0199 return;
0200
0201 if (jack->phantom_jack)
0202 jack->pin_sense = AC_PINSENSE_PRESENCE;
0203 else
0204 jack->pin_sense = read_pin_sense(codec, jack->nid,
0205 jack->dev_id);
0206
0207
0208 if (jack->gating_jack &&
0209 !snd_hda_jack_detect_mst(codec, jack->gating_jack, jack->dev_id))
0210 jack->pin_sense &= ~AC_PINSENSE_PRESENCE;
0211
0212 jack->jack_dirty = 0;
0213
0214
0215 if (jack->gated_jack) {
0216 struct hda_jack_tbl *gated =
0217 snd_hda_jack_tbl_get_mst(codec, jack->gated_jack,
0218 jack->dev_id);
0219 if (gated) {
0220 gated->jack_dirty = 1;
0221 jack_detect_update(codec, gated);
0222 }
0223 }
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233 void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
0234 {
0235 struct hda_jack_tbl *jack = codec->jacktbl.list;
0236 int i;
0237
0238 for (i = 0; i < codec->jacktbl.used; i++, jack++)
0239 if (jack->nid)
0240 jack->jack_dirty = 1;
0241 }
0242 EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all);
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
0254 {
0255 struct hda_jack_tbl *jack =
0256 snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
0257 if (jack) {
0258 jack_detect_update(codec, jack);
0259 return jack->pin_sense;
0260 }
0261 return read_pin_sense(codec, nid, dev_id);
0262 }
0263 EXPORT_SYMBOL_GPL(snd_hda_jack_pin_sense);
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 int snd_hda_jack_detect_state_mst(struct hda_codec *codec,
0275 hda_nid_t nid, int dev_id)
0276 {
0277 struct hda_jack_tbl *jack =
0278 snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
0279 if (jack && jack->phantom_jack)
0280 return HDA_JACK_PHANTOM;
0281 else if (snd_hda_jack_pin_sense(codec, nid, dev_id) &
0282 AC_PINSENSE_PRESENCE)
0283 return HDA_JACK_PRESENT;
0284 else
0285 return HDA_JACK_NOT_PRESENT;
0286 }
0287 EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state_mst);
0288
0289 static struct hda_jack_callback *
0290 find_callback_from_list(struct hda_jack_tbl *jack,
0291 hda_jack_callback_fn func)
0292 {
0293 struct hda_jack_callback *cb;
0294
0295 if (!func)
0296 return NULL;
0297
0298 for (cb = jack->callback; cb; cb = cb->next) {
0299 if (cb->func == func)
0300 return cb;
0301 }
0302
0303 return NULL;
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 struct hda_jack_callback *
0318 snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
0319 int dev_id, hda_jack_callback_fn func)
0320 {
0321 struct hda_jack_tbl *jack;
0322 struct hda_jack_callback *callback = NULL;
0323 int err;
0324
0325 jack = snd_hda_jack_tbl_new(codec, nid, dev_id);
0326 if (!jack)
0327 return ERR_PTR(-ENOMEM);
0328
0329 callback = find_callback_from_list(jack, func);
0330
0331 if (func && !callback) {
0332 callback = kzalloc(sizeof(*callback), GFP_KERNEL);
0333 if (!callback)
0334 return ERR_PTR(-ENOMEM);
0335 callback->func = func;
0336 callback->nid = jack->nid;
0337 callback->dev_id = jack->dev_id;
0338 callback->next = jack->callback;
0339 jack->callback = callback;
0340 }
0341
0342 if (jack->jack_detect)
0343 return callback;
0344 jack->jack_detect = 1;
0345 if (codec->jackpoll_interval > 0)
0346 return callback;
0347 err = snd_hda_codec_write_cache(codec, nid, 0,
0348 AC_VERB_SET_UNSOLICITED_ENABLE,
0349 AC_USRSP_EN | jack->tag);
0350 if (err < 0)
0351 return ERR_PTR(err);
0352 return callback;
0353 }
0354 EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback_mst);
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
0366 int dev_id)
0367 {
0368 return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback_mst(codec,
0369 nid,
0370 dev_id,
0371 NULL));
0372 }
0373 EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
0384 hda_nid_t gating_nid)
0385 {
0386 struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid, 0);
0387 struct hda_jack_tbl *gating =
0388 snd_hda_jack_tbl_new(codec, gating_nid, 0);
0389
0390 WARN_ON(codec->dp_mst);
0391
0392 if (!gated || !gating)
0393 return -EINVAL;
0394
0395 gated->gating_jack = gating_nid;
0396 gating->gated_jack = gated_nid;
0397
0398 return 0;
0399 }
0400 EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
0413 const struct hda_jack_keymap *keymap,
0414 hda_nid_t jack_nid)
0415 {
0416 const struct hda_jack_keymap *map;
0417 struct hda_jack_tbl *key_gen = snd_hda_jack_tbl_get(codec, key_nid);
0418 struct hda_jack_tbl *report_to = snd_hda_jack_tbl_get(codec, jack_nid);
0419
0420 WARN_ON(codec->dp_mst);
0421
0422 if (!key_gen || !report_to || !report_to->jack)
0423 return -EINVAL;
0424
0425 key_gen->key_report_jack = jack_nid;
0426
0427 if (keymap)
0428 for (map = keymap; map->type; map++)
0429 snd_jack_set_key(report_to->jack, map->type, map->key);
0430
0431 return 0;
0432 }
0433 EXPORT_SYMBOL_GPL(snd_hda_jack_bind_keymap);
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
0444 int button_state)
0445 {
0446 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, jack_nid);
0447
0448 if (!jack)
0449 return;
0450
0451 if (jack->key_report_jack) {
0452 struct hda_jack_tbl *report_to =
0453 snd_hda_jack_tbl_get(codec, jack->key_report_jack);
0454
0455 if (report_to) {
0456 report_to->button_state = button_state;
0457 return;
0458 }
0459 }
0460
0461 jack->button_state = button_state;
0462 }
0463 EXPORT_SYMBOL_GPL(snd_hda_jack_set_button_state);
0464
0465
0466
0467
0468
0469 void snd_hda_jack_report_sync(struct hda_codec *codec)
0470 {
0471 struct hda_jack_tbl *jack;
0472 int i, state;
0473
0474
0475 jack = codec->jacktbl.list;
0476 for (i = 0; i < codec->jacktbl.used; i++, jack++)
0477 if (jack->nid)
0478 jack_detect_update(codec, jack);
0479
0480
0481
0482
0483 jack = codec->jacktbl.list;
0484 for (i = 0; i < codec->jacktbl.used; i++, jack++)
0485 if (jack->nid) {
0486 if (!jack->jack || jack->block_report)
0487 continue;
0488 state = jack->button_state;
0489 if (get_jack_plug_state(jack->pin_sense))
0490 state |= jack->type;
0491 snd_jack_report(jack->jack, state);
0492 if (jack->button_state) {
0493 snd_jack_report(jack->jack,
0494 state & ~jack->button_state);
0495 jack->button_state = 0;
0496 }
0497 }
0498 }
0499 EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
0500
0501
0502 static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
0503 {
0504 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
0505 switch (get_defcfg_device(def_conf)) {
0506 case AC_JACK_LINE_OUT:
0507 case AC_JACK_SPEAKER:
0508 return SND_JACK_LINEOUT;
0509 case AC_JACK_HP_OUT:
0510 return SND_JACK_HEADPHONE;
0511 case AC_JACK_SPDIF_OUT:
0512 case AC_JACK_DIG_OTHER_OUT:
0513 return SND_JACK_AVOUT;
0514 case AC_JACK_MIC_IN:
0515 return SND_JACK_MICROPHONE;
0516 default:
0517 return SND_JACK_LINEIN;
0518 }
0519 }
0520
0521 static void hda_free_jack_priv(struct snd_jack *jack)
0522 {
0523 struct hda_jack_tbl *jacks = jack->private_data;
0524 jacks->nid = 0;
0525 jacks->jack = NULL;
0526 }
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid,
0542 int dev_id, const char *name, bool phantom_jack,
0543 int type, const struct hda_jack_keymap *keymap)
0544 {
0545 struct hda_jack_tbl *jack;
0546 const struct hda_jack_keymap *map;
0547 int err, state, buttons;
0548
0549 jack = snd_hda_jack_tbl_new(codec, nid, dev_id);
0550 if (!jack)
0551 return 0;
0552 if (jack->jack)
0553 return 0;
0554
0555 if (!type)
0556 type = get_input_jack_type(codec, nid);
0557
0558 buttons = 0;
0559 if (keymap) {
0560 for (map = keymap; map->type; map++)
0561 buttons |= map->type;
0562 }
0563
0564 err = snd_jack_new(codec->card, name, type | buttons,
0565 &jack->jack, true, phantom_jack);
0566 if (err < 0)
0567 return err;
0568
0569 jack->phantom_jack = !!phantom_jack;
0570 jack->type = type;
0571 jack->button_state = 0;
0572 jack->jack->private_data = jack;
0573 jack->jack->private_free = hda_free_jack_priv;
0574 if (keymap) {
0575 for (map = keymap; map->type; map++)
0576 snd_jack_set_key(jack->jack, map->type, map->key);
0577 }
0578
0579 state = snd_hda_jack_detect_mst(codec, nid, dev_id);
0580 snd_jack_report(jack->jack, state ? jack->type : 0);
0581
0582 return 0;
0583 }
0584 EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl_mst);
0585
0586 static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
0587 const struct auto_pin_cfg *cfg,
0588 const char *base_name)
0589 {
0590 unsigned int def_conf, conn;
0591 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
0592 int err;
0593 bool phantom_jack;
0594
0595 WARN_ON(codec->dp_mst);
0596
0597 if (!nid)
0598 return 0;
0599 def_conf = snd_hda_codec_get_pincfg(codec, nid);
0600 conn = get_defcfg_connect(def_conf);
0601 if (conn == AC_JACK_PORT_NONE)
0602 return 0;
0603 phantom_jack = (conn != AC_JACK_PORT_COMPLEX) ||
0604 !is_jack_detectable(codec, nid);
0605
0606 if (base_name)
0607 strscpy(name, base_name, sizeof(name));
0608 else
0609 snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
0610 if (phantom_jack)
0611
0612 strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
0613 err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL);
0614 if (err < 0)
0615 return err;
0616
0617 if (!phantom_jack)
0618 return snd_hda_jack_detect_enable(codec, nid, 0);
0619 return 0;
0620 }
0621
0622
0623
0624
0625
0626
0627 int snd_hda_jack_add_kctls(struct hda_codec *codec,
0628 const struct auto_pin_cfg *cfg)
0629 {
0630 const hda_nid_t *p;
0631 int i, err;
0632
0633 for (i = 0; i < cfg->num_inputs; i++) {
0634
0635
0636 if (cfg->inputs[i].is_headphone_mic) {
0637 if (auto_cfg_hp_outs(cfg) == 1)
0638 err = add_jack_kctl(codec, auto_cfg_hp_pins(cfg)[0],
0639 cfg, "Headphone Mic");
0640 else
0641 err = add_jack_kctl(codec, cfg->inputs[i].pin,
0642 cfg, "Headphone Mic");
0643 } else
0644 err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg,
0645 NULL);
0646 if (err < 0)
0647 return err;
0648 }
0649
0650 for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
0651 err = add_jack_kctl(codec, *p, cfg, NULL);
0652 if (err < 0)
0653 return err;
0654 }
0655 for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
0656 if (*p == *cfg->line_out_pins)
0657 break;
0658 err = add_jack_kctl(codec, *p, cfg, NULL);
0659 if (err < 0)
0660 return err;
0661 }
0662 for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
0663 if (*p == *cfg->line_out_pins)
0664 break;
0665 err = add_jack_kctl(codec, *p, cfg, NULL);
0666 if (err < 0)
0667 return err;
0668 }
0669 for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
0670 err = add_jack_kctl(codec, *p, cfg, NULL);
0671 if (err < 0)
0672 return err;
0673 }
0674 err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, NULL);
0675 if (err < 0)
0676 return err;
0677 err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, NULL);
0678 if (err < 0)
0679 return err;
0680 return 0;
0681 }
0682 EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls);
0683
0684 static void call_jack_callback(struct hda_codec *codec, unsigned int res,
0685 struct hda_jack_tbl *jack)
0686 {
0687 struct hda_jack_callback *cb;
0688
0689 for (cb = jack->callback; cb; cb = cb->next) {
0690 cb->jack = jack;
0691 cb->unsol_res = res;
0692 cb->func(codec, cb);
0693 }
0694 if (jack->gated_jack) {
0695 struct hda_jack_tbl *gated =
0696 snd_hda_jack_tbl_get_mst(codec, jack->gated_jack,
0697 jack->dev_id);
0698 if (gated) {
0699 for (cb = gated->callback; cb; cb = cb->next) {
0700 cb->jack = gated;
0701 cb->unsol_res = res;
0702 cb->func(codec, cb);
0703 }
0704 }
0705 }
0706 }
0707
0708
0709
0710
0711
0712
0713 void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
0714 {
0715 struct hda_jack_tbl *event;
0716 int tag = (res & AC_UNSOL_RES_TAG) >> AC_UNSOL_RES_TAG_SHIFT;
0717
0718 if (codec->dp_mst) {
0719 int dev_entry =
0720 (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
0721
0722 event = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry);
0723 } else {
0724 event = snd_hda_jack_tbl_get_from_tag(codec, tag, 0);
0725 }
0726 if (!event)
0727 return;
0728
0729 if (event->key_report_jack) {
0730 struct hda_jack_tbl *report_to =
0731 snd_hda_jack_tbl_get_mst(codec, event->key_report_jack,
0732 event->dev_id);
0733 if (report_to)
0734 report_to->jack_dirty = 1;
0735 } else
0736 event->jack_dirty = 1;
0737
0738 call_jack_callback(codec, res, event);
0739 snd_hda_jack_report_sync(codec);
0740 }
0741 EXPORT_SYMBOL_GPL(snd_hda_jack_unsol_event);
0742
0743
0744
0745
0746
0747
0748
0749
0750 void snd_hda_jack_poll_all(struct hda_codec *codec)
0751 {
0752 struct hda_jack_tbl *jack = codec->jacktbl.list;
0753 int i, changes = 0;
0754
0755 for (i = 0; i < codec->jacktbl.used; i++, jack++) {
0756 unsigned int old_sense;
0757 if (!jack->nid || !jack->jack_dirty || jack->phantom_jack)
0758 continue;
0759 old_sense = get_jack_plug_state(jack->pin_sense);
0760 jack_detect_update(codec, jack);
0761 if (old_sense == get_jack_plug_state(jack->pin_sense))
0762 continue;
0763 changes = 1;
0764 call_jack_callback(codec, 0, jack);
0765 }
0766 if (changes)
0767 snd_hda_jack_report_sync(codec);
0768 }
0769 EXPORT_SYMBOL_GPL(snd_hda_jack_poll_all);
0770